Introducción
En un estudio de queso Cheddar realizado en el Valle de Latrobe (Victoria, Australia), se estudiaron muestras de queso en las que se analizó su composición quÃmica y fueron dadas a probar a distintos sujetos para que valoraran su sabor. Los valores asignados a cada queso son el resultado de combinar las distintas valoraciones.
El DataFrame cheddar de la librerÃa faraway consiste de 30 muestras de queso Cheddar en las que se ha medido el sabor (taste) y las concentraciones de ácido acético (Acetic), ácido sulfhÃdrico (H2S) y lactosa (Lactic).
Tenenemos un conjunto de datos en el que se recogen observaciones de una cata de quesos, nuestras variables son:
· Taste: una valoración subjetiva de los jueces.
· Acetic: la concentración de ácido acético.
· H2S: la concentración de sulfito de hidrógeno.
· Lactic: concentración de ácido láctico.
Cargamos los datos y enseñamos las primeras observaciones.
Si en nuestro dataset tuviesemos entradas vacÃas (NA), tenemos varias posibilidades para lidiar con este problema:
No utilizar/Eliminar las observación que contienen valores.
No utilizar/Eliminar las variables que contienen las entradas vacÃas.
Intentar completar los valores. Existen métodos menos y más sofisitcados:
Remplezar con la media, media o moda.
Crear una nueva categorÃa para valores vacÃos.
Utilizar algún modelo de regresión.
Usar un modelo de K-Nearest Neighbors (KNN).
Pero en nuestro caso evaluamos y no hay valores missing.
En nuestro caso, todas las variables son numéricas (cuantitativas). No hay ninguna variable categórica ni cualitativa. Si hubiese, tendrÃamos que transformarlas en variables binarias. Para ello, deberÃamos hacer encoding a variables binarias, el lenguaje de programación R nos permite utilizar as.numeric.
Con estas variables vamos a intentar explicar cómo los valores observados de una variable Y (taste) dependen de los valores de otras variables (Acetic, H2S, Latcic), a través de una relación funcional lineal del tipo Y = f(X). También vamos a intentar predecir el valor de la variable Y para valores no observados de las variables X.
Tenemos 30 observaciones en nuestro dataset. Ahora procedemos a divirlo en el conjunto de train y test. El primero lo utilizaremos para entrenar nuestros modelos y el segundo lo usaremos para cuantificar el error de los modelos.
Para asegurar que sea reproducible utilizamos una semilla, que permite fijar los valores pseudoaleatorios obtenidos en muchas de las funciones utilizadas.
Hacemos un estudio preliminar de nuestras variables. Mostramos un scatter plot de cada variable contrastada con el resto. Esto permite ver a ojo si algún par de variables tiene correlación.

Ahora, utilizamos la función summary de R, la cual nos permite estimar algunos de las caracterÃsticas de la distribución del dataset. La siguiente tabla nos muestra los estadÃsticos más comunes: el mÃnimo, máximo, mediana, media y el 1er y 3er cuartil.
taste Acetic H2S Lactic
Min. : 0.70 Min. :4.477 Min. : 2.996 Min. :0.860
1st Qu.:13.55 1st Qu.:5.237 1st Qu.: 3.978 1st Qu.:1.250
Median :20.95 Median :5.425 Median : 5.329 Median :1.450
Mean :24.53 Mean :5.498 Mean : 5.942 Mean :1.442
3rd Qu.:36.70 3rd Qu.:5.883 3rd Qu.: 7.575 3rd Qu.:1.667
Max. :57.20 Max. :6.458 Max. :10.199 Max. :2.010
Hacemos las gráficas de dispersión entre la variable respuesta taste y las variables predictoras Acetic, H2S, Lactic.

Podemos observar que la que aperentemente guarda una menor relación lineal con taste es la variable Acetic, este hecho será reafirmado más adelante.
Estudio y evaluación del modelo completo.
Intentaremos predecir la variable taste usando el resto de variables. Para empezar, definimos el modelo completo, el cual se usan todas las variables para nuestro modelo lineal múltiple.
\[
Y_i =\beta_0 + \beta_1 x_{i1} + \dots + \beta_{p-1}x_{i(p-1)} + \epsilon_i,\quad i=1,\dots,n
\] donde \(Y_i\) es el valor de la variable respuesta para el individuo \(i\)-ésimo, \(\beta_0\) y los \(\beta_j\) son los parámetros \(j = 1, ..., p - 1\), \(x_{ij}\) son los elementos de la matriz de las variables explicativas \(\epsilon_i\) es el término del error aleatorio que suponemos que se distribuye como una \(\mathcal{N}(0,\sigma^2)\), donde \(\sigma^2\) es la varianza que suele ser desconocida.
Resolución usando librerias de R
Podemos utilizar la función \(lm\), ya programada en R. Definimos el modelo completo, y comprobamos las betas:
\[
taste \sim Acetic \, + \, H2S \, + \, Lactic, \, \, data = cheddar
\]
Estudiemos preliminarmente si es un modelo lineal adecuado, para ello comprobaremos las hipótesis estándar del modelo lineal de regresión usando el test de normalidad Shapiro-Wilk. La función \(shapiro.test\) le pasamos por parámetro el residuo/error de cada una de las muestras y nos devuelve un \(p\)-valor.
Observamos que estamos en la hipótesis de que el error nuestro modelo se distribuye de manera normal, ya que el p-valor es \(0.8865 > 0.05\).
Otro aspecto que debemos saber es si la media de los errores será nula o no, para ello usamos una función implementada en R que nos afirma que en nuestro caso esto es asÃ. Respecto a los errores tenemos que saber que se distribuyen con varianza constante, que de manera análoga comprobamos, teniendo p-valores lo suficientemente bajos como para rechazar varianza no constante. De igual manera tenemos que no hay autocorrelación en el modelo completo.
Una vez hemos concluido que aunque estamos en las hipótesis de regresión lineal el modelo completo a pesar de ser el más complejo probablemente da resultados similares a otro más simple.
Call:
lm(formula = taste ~ ., data = cheddar)
Residuals:
Min 1Q Median 3Q Max
-17.390 -6.612 -1.009 4.908 25.449
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -28.8768 19.7354 -1.463 0.15540
Acetic 0.3277 4.4598 0.073 0.94198
H2S 3.9118 1.2484 3.133 0.00425 **
Lactic 19.6705 8.6291 2.280 0.03108 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
s: 10.13 on 26 degrees of freedom
Multiple R-squared: 0.6518,
Adjusted R-squared: 0.6116
F-statistic: 16.22 on 3 and 26 DF, p-value: 3.81e-06
Tras realizar el summary del modelo, una observación muy importante que sacamos es que el p-valor de Acetic es muy grande (0.94) por lo que no va a ser una variable significativa y por tanto con casi toda seguridad no tiene impacto real en el modelo.
Por el contrario el resto de variables sà son significativas por tener p-valor inferior a 0.5, destacando Lactic por tener un beta mayor que H2S, lo que ppuede hacernos llegar a pensar que cobre más importancia en un modelo final. #### Correlaciones y tabla de resultados con el estudio de sus p-valores Usamos el paquete \(GGplot\) de R, el cual nos permite visualizar la correlación y dispersión entre las distintas variables.

Pdemos apreciar que la variable con menor coefeciente de correlación de Pearson es Acetic,mientra que el resto de variables tienen un valor bastante mayor. Cabe destacar que todos tienen un signo positivo, lo que nos dice que en general al aumentar una aumenta la otra.
¿Tiene outliers nuestra muestra?
Para comprobarlo basta realizar el test de Bonferroni sobre nuestro modelo completo:
Concluimos con un nivel \(\alpha\) = 0.05 que no tenemos ningún outlier en nuestra. Lo más cercano a un outlier que tenemos es la observación número 15, que tiene un valor Bonferroni p de 0.17453 (no se acerca a 0.05). Por tanto, no tenemos razones por las que eliminar alguna observación inusual de nuestro conjunto de datos.
Esto se puede comprobar graficamente a través del siguiente gráfico, el cual mide la influencia de cada observación sobre cada una de las betas de nuestro modelo.

Vemos que la que más influye es la antes mencionada observación 15 y por tanto deberÃamos considerar si es outlier. Hemos comprobado que sucederÃa al eliminar esa observación de la muestra, y si bien mejoraba algún p-valor de las hipótesis de regresión, en otros los empeoraba, asà que hemos decidido no eliminarla y esperarnos a ver el caso en las seeds que estudiaremos con más detalles si sale de la muestra como observación influyente.
¿Cuál es el mejor modelo?
Como dice el Principio de la Navaja de Ockham, a menudo la explicación más simple es la correcta. Queremos seleccionar predictores que explican los datos de la manera más simple posible, sin disminuir la calidad de las predicciones mucho.
Separacion del dataset en conjuntos de entrenamiento y test (70-30%)
Hemos escogido distintas semillas para estar en condiciones de realizar un estudio más amplio, en la elección de las mismas se ha intentado evitar aquellas que generaban muestras demasiado similares. Las semillas usadas son 1, 1100 y 5 posteriormente se introducirán dos más para afinar en el cálculo de errores.
Consideremos los conjuntos de entrenamiento resultantes de las semillas: train.1(semilla 1), train.2(semilla 1100), train.3(semilla 5).Veaamos que modelos debemos considerar en base a nuestros train.
Método Backward
Partimos del modelo completo estudiado en la sección anterior, eso sÃ, evaluado en nuestros respectivos train y aplicamos con \(\alpha\) = 0.05, el método de Backward, que consiste en eliminar la variable que menos influya a la predicción. Primero realizamos una iteración explÃcita del método sobre la primera semilla, y posteriormente se construyen a través de la libreria mixlm de R.
Eliminamos Acetic del modelo debido que su p-valor es >0.05.
Repetimos el proceso con la variable H2S, ya que tiene un p-valor mayor que \(\alpha = 0.05\)
El p-valor es menor que \(\alpha = 0.05\), por lo que hemos concluido, ya que no tenemos suficiente certeza para poder eliminar otra variable.Por tanto, tenemos como resultado que la variable que mejor explica el taste es Lactic. Modelo resultante: taste ~ Lactic, data = cheddar[train.1,].
Por otro lado los modelos backward resultantes por mixlm son:
taste ~ H2S + Lactic, data = cheddar[train.2,] y por otro lado taste ~ H2S + Lactic, data = cheddar[train.3,].
Método Forward
El método Forward consiste en empezar con un modelo de una variable y vamos añadiendo las que más influyan, desarrollaremos el primer modelo de forma explÃcita y el resto los generaremos con mixlm. De esta manera tenemos:
Actualizamos añadiendo Lactic por tener el menor p-valor.
Con nivel de significación \(\alpha\) = 0.05 este serÃa nuestro modelo final. Modelo resultante = taste ~ Lactic, data = cheddar[train.1,]
Por otro lado los modelos forward resultantes por mixlm son:
taste ~ H2S + Lactic, data = cheddar[train.2,] y por otro lado taste ~ H2S + Lactic, data = cheddar[train.3,].
Construcción por criterios
En esta subsección trataremos de encontrar un candidato a mejor modelo, construyendo nuestros modelos usando distintos enfoques. Tras aplicar los siguientes criterios a la hora del desarrollo de modelos: \(R^2\) ajustado, Cp de Mallows, Criterio de Informacion de Bayes (BIC), Criterio de Informacion de Akaike (AIC) eligiendo el que nos de un menor o mayor coeficiente según el método (los desarrolos se pueden encontrar en el script), llegamos a las siguientes conclusiones:
solo aparece un modelo nuevo usando el criterio del estadÃstico \(R^2\) para la primera semilla, taste ~ H2S + Lactic, data = cheddar[train.1,].
Notamos que la combinación de H2S + L aparece en todos nuestros conjuntos de entrenamiento en algún momento, es candidata a ser nuestra mejor elección.
Comparamos los modelos obtenidos hasta ahora en su respectiva muestra de entrenamiento con el modelo completo en ese conjunto de entrenamiento.
Analysis of Variance Table
Model 1: taste ~ Lactic
Model 2: taste ~ Acetic + H2S + Lactic
Res.Df RSS Df Sum of Sq F Pr(>F)
1 19 1853.5
2 17 1410.7 2 442.84 2.6683 0.09821 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Con estos p-valores podemos decir que con un nivel de significación \(\alpha\) ningún modelo es notablemente diferente de su contraparte salvo en el caso de los modelos resultantes en train2 esto puede ser por la cantidad de observaciones influyentes presentes en la muestra, lo trataremos en la siguiente sección.
Diagnostico: Comprobaciones de hipotesis, outliers y observaciones influyentes
En esta sección estudiaremos si nuestros modelos cumplen las condiciones necesarias de un modelo de regresión lineal.
Nuestro enfoque consistirá en un análisis gráfico, acompañado de tests estadÃsticos en los casos en los que se aprecie una discrepancia notable.
¿Son nuestros modelos, modelos de regresión lineal?: Comprobación de hipótesis.
En la sección 3 se toma un enfoque naïve a la hora de construir los modelos, ya que no hemos estudiado si hay observaciones influyentes, podrÃamos tener una muestra que no es la adecuada para el estudio de nuestros datos.
Un modelo de regresión lineal debe satisfacer las siguientes hipótesis con nivel de significación \(\alpha\) adecuado:
- Los errores \(\epsilon_{i}\) tienen distribución normal.
- Los errores \(\epsilon_{i}\) tienen media cero.
- Los errores \(\epsilon_{i}\) tienen varianza constante.
- Los errores \(\epsilon_{i}\) no están correlacionados.
Podemos observar que se verifican a nivel de significación \(\alpha\) = 0.05 se verifican todas las hipótesis de modelo de regresión lineal. En las siguientes gráficas podemos observar como los residuos de los modelos taste ~ H2S + L de los conjuntos train2 y train3 se comportan mejor que cualquiera de los modelos propuestos en la muestra train1


Posteriormente, realizamos un estudio de la colinealidad. Para ello, observamos que el modelo taste ~ Lactic , data=cheddar[train.1,] solo tiene un predictor luego no hay presente ningún tipo colinealidad.
Nuestros valores son muy buenos, entendiendo por bueno VIF < 10, por lo tanto no tenenemos que preocuparnos de una colinealidad grave entre las variables.
Estudio de outliers
A fin de obtener distintos puntos de vista utilizaremos dos métodos, un valor de Bonferroni en un estadÃstico \(t_{1-\frac{\alpha}{2n};n-p-1}\) y la función outlierTest que utiliza p-valores de Bonferroni obtenidos a través de t-tests.
En los cuatro modelos y bajo los dos criterios no se obtiene ninguna observación que se pueda aceptar como outlier a nivel de significación \(\alpha\) = 0.05
Estudio de observaciones Influyentes
Al igual que en la anterior sección a fin de poder encontrar el criterio que mejor se ajuste a nuestro modelo, en el que hay que tener en cuenta que es una muestra de tamaño reducido, utilizaremos varios criterios, además de distintas técnicas gráficas. Los criterios usados serán:
1.Criterio 1: valores leverage (hii) mayores que \(\frac{2p}{n}\).
2.Criterio 2: valores |DFFITS| son mayores que \(2 \cdot \sqrt{\frac{2p}{n}}\).
3.Criterio 3: valores |DFBETAS| mayores que \(2 \cdot \sqrt{\frac{2p}{n}}\).
4.Criterio 4: InfluencePlot.
En la siguiente tabla observamos las observaciones influyentes obtenidas por cada criterio.
Tomamos la decisión de elegir los elementos que se repitan en varios ya que si eliminásemos los del criterio 3 el resultado serÃa demasiado pequeño para ser apto para la regresión lineal. Nuestro criterio a seguir es que estén en al menos dos criterios de los restantes.

Estas observaciones son las presentes en la cuarta columna de la tabla y en general son en las primeras en las que nos fijemos a la hora de ver si las tomamos como influyentes o no.
Bajo nuestro criterio quedarÃan como posibles influyentes las siguientes observaciones:
Ahora es cuando tenemos que determinar si van a ser influyentes o no, esto lo veremos comparando los modelos con las muestras de entrenamiento sin eliminar influyentes y con las muestras modificadas, y evaluar si mejoran o empeoran los p-valores de las hipótesis de los modelos de regresión.
taste ~ + Lactic, data = cheddar[train.1,] vs taste ~ Lactic, data = cheddar[train.1inf,]
Nuestras hipótesis del modelo lineal se ven notablemente mejoradas, tenemos una distribución más parecida a una normal, mejor distribuida en torno a una lineal.
Realizamos un pequeño intercambio en el que nuestra varianza parece menos constante pero se mantiene por encima de todos los niveles de significación habituales.
Tomamos la decisión de actualizar cheddar[train.1,] con cheddar[traininf.1,], que es la versión sin observaciones influyentes. ### taste ~ H2S + Lactic, data = cheddar[train.1,] vs taste ~ H2S + Lactic, data = cheddar[train.1critinf,]
Este es un caso un tanto particular, tenemos unos datos perfectamente distribuidos, pero ya lo estaban antes practicamente. A cambio de eso perdemos un cierto grado de linealidad que hay que tener en cuenta, en este caso no hay una diferencia tan notable con el modelo como en que solo incorporaba a Lactic.
Tomamos la decisión de actualizar cheddar[train.1crit,] con cheddar[train.1critinf,], que es la versión sin observaciones influyentes.
taste ~ H2S + Lactic, data = cheddar[train.2,] vs taste ~ H2S + Lactic, data = cheddar[train.2inf,]
En cierta manera es notable que al eliminar nuestras influyentes y en un dataset tan pequeño no genere a penas diferencia, en todo caso nos mejora todas las hipótesis del modelo lineal, se puede afirmar que es un modelo mejor para trabajar sobre el a priori.
Tomamos la decisión de actualizar cheddar[train.2,] con cheddar[traininf.2,], que es la versión sin observaciones influyentes.
taste ~ H2S + Lactic, data = cheddar[train.3,]
En este modelo, bajo el criterio de elección de observaciones influyentes que elegimos para tratar nuestros datos, este modelo no presentaba ninguna observación influyente, por lo que se mantiene como está.
Errores de Test. Comparacion de Modelos
Nuestro razonamiento para enfrentarnos a esta sección es el siguiente, nos han salido dos modelos posibles y para comprender cual se ajusta mejor a nuestros datos vamos a escoger cinco seeds y evaluar cada modelo en todas ellas, a fin de hacer una media de los errores.
Para esto usamos las tres seeds que hemos utilizado a lo largo del documento, y le añadimos otras dos elegidas al azar. Nótese que evaluar en la primera seed ya está hecho, pues en esta nos salÃan los dos modelos a considerar. Además en las seeds dos y tres ya está hecho para el modelo con H2S + Lactic, pero hay que repetir el proceso para el otro modelo. De esta manera realizamos los mismos cálculos que los realizados en la parte de diagnóstico, sobre las combinaciones. Esto es, nos aseguramos que cada modelo con todos los train cumpla las hipótesis de normalidad, media de errores nula, homocedasticidad, linealidad y autocorrelación. Después de esto nos planteamos si tiene datos influyentes según las funciones adecuadas, en caso de tenerlos realizamos una prueba. los quitamos del train y vemos si se mejora el p-valor de alguna de las caracterÃsticas anteriores y en base a eso decidimos si eliminamos las observaciones influyentes o no.
Con todo eso realizado llegamos a la siguiente tabla, que nos permite asumir como validos todos los casos y calcular sus errores.
Calculamos los errores de cada método como la media de los errores del método aplicado en cada seed. De esta manera, el error medio obtenido es:
Como el error del modelo H2S + Lactic es menor, ese es el modelo que llamaremos final y que se ajustará lo mejor posible a los datos de nuestro fichero.
Conclusión: presentación del modelo final
Finalmente por comparación de los errores sabemos que el modelo final que presentamos es: taste ~ H2S + Lactic , que tiene sentido ya que Acetic no era significativa. otro hecho que lo reafirma es que en la construcción de modelos salieron en todos los casos este modelo, salvo en el método backward y en el método forward de la primera semilla.
Presentamos el summary de nuestro modelo, del que sacaremos más informción en un futuro.
A su vez enseñamos los graficos de este modelo:

Ahora vamos a asegurarnos que verifica las hipótesis para una regresión lineal y además de revisar con outlierTest que no tenemos outliers. También planteamos una hipótesis sobre la nulidad de la media de los errores y vemos que su varianza es constante además de calcularla.
Dicho esto procedemos a la presentación del modelo con sus betas asociados, que si bien se pueden recoger del summary, también los calculamos de forma matricial igual que se hizo con el modelo completo en su momento.
El resultado serÃa taste ~ -27.591815 +3.9946267 H2S +19.887204 Lactic Nótese que sigue siendo acorde al modelo completo donde el \(\beta\) de Lactic es muy superior en comparación al de H2S.
Presentamos ahora \(R^{2}\) y \(R^{2}_{adj}\), estas como antes se pueden recoger directamente del summary, también las calculamos a partir de los errores y la tabla anova, dando el resultado de 0.6517024 y 0.6259025 respectivamente. Además presentamos el vector de p-valores.
Observamos que todos los p-valores están por debajo de nuestra alpha de referencia.
También presentamos intervalos para las betas de Bonferroni y Scheffé:
Finalmente buscamos una representación de la regresión que tenemos en 3 dimensiones ya que el modelo final consta de una variable respuesta y dos predictoras y vemos el plano de regresión, marcando en rojo las observaciones que peor se ajustan.

LS0tDQp0aXRsZTogJ1JlZ3Jlc2nDs246IE1vZGVsb3MgRXN0YWTDrXN0aWNvcycNCmF1dGhvcjoNCi0gbmFtZTogRGFuaWVsIEzDs3BleiBNb250ZXJvDQotIG5hbWU6IFJvZHJpZ28gZGUgbGEgTnVleiBNb3JhbGVkYQ0KLSBuYW1lOiBKb3PDqSBHYXJjw61hIFJlYm9sbG8NCi0gbmFtZTogRGF2aWQgUGFycm8gUGxhemENCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogMw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogIHBkZl9kb2N1bWVudDoNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnMycNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KYWx3YXlzX2FsbG93X2h0bWw6IHllcw0KYWJzdHJhY3Q6IHwNCiAgSGVtb3MgYW5hbGl6YWRvIGNvbiBsYXMgaGVycmFtaWVudGFzIHByb3BvcmNpb25hZGFzIGVuIGVsIGN1cnNvIGRlIE1vZGVsb3MgRXN0YWTDrXN0aWNvcyBlbCBjb25qdW50byBkZSBkYXRvcywgKkNoZWRkYXIqLCBkaXN0cmlidWlkbyBlbiBsYSBsaWJyZXLDrWEgRmFyYXdheSBkZSBSLiBQYXJhIGVsbG8gaGVtb3MgdXRpbGl6YWRvIGRpdmVyc2FzIHTDqWNuaWNhcyBkZSByZWdyZXNpw7NuIGxpbmVhbC4NCnN1YnRpdGxlOiAnQ29uanVudG8gZGUgRGF0b3M6IENoZWRkYXIgRmFyYXdheScNCi0tLQ0KDQoNCiMgSW50cm9kdWNjacOzbg0KDQpFbiB1biBlc3R1ZGlvIGRlIHF1ZXNvIENoZWRkYXIgcmVhbGl6YWRvIGVuIGVsIFZhbGxlIGRlIExhdHJvYmUgKFZpY3RvcmlhLCBBdXN0cmFsaWEpLCBzZSBlc3R1ZGlhcm9uIG11ZXN0cmFzIGRlIHF1ZXNvIGVuIGxhcyBxdWUgc2UgYW5hbGl6w7Mgc3UgY29tcG9zaWNpw7NuIHF1w61taWNhIHkgZnVlcm9uIGRhZGFzIGEgcHJvYmFyIGEgZGlzdGludG9zIHN1amV0b3MgcGFyYSBxdWUgdmFsb3JhcmFuIHN1IHNhYm9yLiBMb3MgdmFsb3JlcyBhc2lnbmFkb3MgYSBjYWRhIHF1ZXNvIHNvbiBlbCByZXN1bHRhZG8gZGUgY29tYmluYXIgbGFzIGRpc3RpbnRhcyB2YWxvcmFjaW9uZXMuIA0KDQpFbCBEYXRhRnJhbWUgKipjaGVkZGFyKiogZGUgbGEgbGlicmVyw61hICoqZmFyYXdheSoqIGNvbnNpc3RlIGRlIDMwIG11ZXN0cmFzIGRlIHF1ZXNvIENoZWRkYXIgZW4gbGFzIHF1ZSBzZSBoYSBtZWRpZG8gZWwgc2Fib3IgKCp0YXN0ZSopIHkgbGFzIGNvbmNlbnRyYWNpb25lcyBkZSDDoWNpZG8gYWPDqXRpY28gKCpBY2V0aWMqKSwgw6FjaWRvIHN1bGZow61kcmljbyAoKkgyUyopIHkgbGFjdG9zYSAoKkxhY3RpYyopLg0KDQoNClRlbmVuZW1vcyB1biBjb25qdW50byBkZSBkYXRvcyBlbiBlbCBxdWUgc2UgcmVjb2dlbiBvYnNlcnZhY2lvbmVzIGRlIHVuYSBjYXRhIGRlDQpxdWVzb3MsIG51ZXN0cmFzIHZhcmlhYmxlcyBzb246ICAgDQoNCg0KKirCtyBUYXN0ZToqKiB1bmEgdmFsb3JhY2nDs24gc3ViamV0aXZhIGRlIGxvcyBqdWVjZXMuICAgDQoNCioqwrcgQWNldGljOioqIGxhIGNvbmNlbnRyYWNpw7NuIGRlIMOhY2lkbyBhY8OpdGljby4NCg0KKirCtyBIMlM6KiogbGEgY29uY2VudHJhY2nDs24gZGUgc3VsZml0byBkZSBoaWRyw7NnZW5vLg0KDQoqKsK3IExhY3RpYzoqKiBjb25jZW50cmFjacOzbiBkZSDDoWNpZG8gbMOhY3RpY28uDQoNCiA8IS0tIEEgbG8gbGFyZ28gZGVsIGRvY3VtZW50byBoYWNlbW9zIHVzbyBkZSBsYXMgc2lndWllbnRlcyBsaWJyZXJpYXMgZGUgUjogLS0+DQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KbGlicmFyeShmYXJhd2F5KQ0KbGlicmFyeShsZWFwcykNCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkoUEFTV1IpDQpsaWJyYXJ5KGNhcikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoR0dhbGx5KQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShzY2F0dGVycGxvdDNkKQ0KbGlicmFyeShsbXRlc3QpDQpsaWJyYXJ5KG1peGxtKQ0KbGlicmFyeShjb3dwbG90KQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkobGVtb24pDQpsaWJyYXJ5KGJyb29tKQ0KbGlicmFyeSh0aWJibGUpDQpgYGANCg0KQ2FyZ2Ftb3MgbG9zIGRhdG9zIHkgZW5zZcOxYW1vcyBsYXMgcHJpbWVyYXMgb2JzZXJ2YWNpb25lcy4NCmBgYHtyIGVjaG89RkFMU0V9DQojIGxvYWQgY2hlZGRhciBjaGVkZGFyDQpkYXRhKGNoZWRkYXIpIA0KaGVhZChjaGVkZGFyKQ0KYGBgDQoNClNpIGVuIG51ZXN0cm8gZGF0YXNldCB0dXZpZXNlbW9zIGVudHJhZGFzIHZhY8OtYXMgKE5BKSwgdGVuZW1vcyB2YXJpYXMgcG9zaWJpbGlkYWRlcyBwYXJhIGxpZGlhciBjb24gZXN0ZSBwcm9ibGVtYToNCg0KKiBObyB1dGlsaXphci9FbGltaW5hciBsYXMgb2JzZXJ2YWNpw7NuIHF1ZSBjb250aWVuZW4gdmFsb3Jlcy4NCg0KKiBObyB1dGlsaXphci9FbGltaW5hciBsYXMgdmFyaWFibGVzIHF1ZSBjb250aWVuZW4gbGFzIGVudHJhZGFzIHZhY8OtYXMuDQoNCiogSW50ZW50YXIgY29tcGxldGFyIGxvcyB2YWxvcmVzLiBFeGlzdGVuIG3DqXRvZG9zIG1lbm9zIHkgbcOhcyBzb2Zpc2l0Y2Fkb3M6DQoNCiAgKyBSZW1wbGV6YXIgY29uIGxhICoqbWVkaWEsIG1lZGlhIG8gbW9kYSoqLg0KDQogICsgQ3JlYXIgdW5hICoqbnVldmEgY2F0ZWdvcsOtYSoqIHBhcmEgdmFsb3JlcyB2YWPDrW9zLg0KDQogICsgVXRpbGl6YXIgYWxnw7puIG1vZGVsbyBkZSAqKnJlZ3Jlc2nDs24qKi4NCg0KICArIFVzYXIgdW4gbW9kZWxvIGRlICoqSy1OZWFyZXN0IE5laWdoYm9ycyAoS05OKSoqLg0KICANClBlcm8gZW4gbnVlc3RybyBjYXNvIGV2YWx1YW1vcyB5IG5vIGhheSB2YWxvcmVzICptaXNzaW5nKi4gIA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBjaGVjayBpZiBhbnkgZW50cnkgaGFzIGEgbWlzc2luZyB2YWx1ZSAoTkEpDQphbnkoaXMubmEoY2hlZGRhcikpDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kc2FwcGx5KGNoZWRkYXIsIGNsYXNzKQ0KYGBgDQoNCkVuIG51ZXN0cm8gY2FzbywgdG9kYXMgbGFzIHZhcmlhYmxlcyBzb24gbnVtw6lyaWNhcyAoKipjdWFudGl0YXRpdmFzKiopLiBObyBoYXkgbmluZ3VuYSB2YXJpYWJsZSBjYXRlZ8OzcmljYSBuaSBjdWFsaXRhdGl2YS4gU2kgaHViaWVzZSwgdGVuZHLDrWFtb3MgcXVlIHRyYW5zZm9ybWFybGFzIGVuIHZhcmlhYmxlcyBiaW5hcmlhcy4gUGFyYSBlbGxvLCBkZWJlcsOtYW1vcyBoYWNlciBlbmNvZGluZyBhIHZhcmlhYmxlcyBiaW5hcmlhcywgZWwgbGVuZ3VhamUgZGUgcHJvZ3JhbWFjacOzbiBSIG5vcyBwZXJtaXRlIHV0aWxpemFyICphcy5udW1lcmljKi4NCg0KQ29uIGVzdGFzIHZhcmlhYmxlcyB2YW1vcyBhIGludGVudGFyICoqZXhwbGljYXIqKiBjw7NtbyBsb3MgdmFsb3JlcyBvYnNlcnZhZG9zIGRlIHVuYSB2YXJpYWJsZSBZICh0YXN0ZSkgZGVwZW5kZW4gZGUgbG9zIHZhbG9yZXMgZGUgb3RyYXMgdmFyaWFibGVzIChBY2V0aWMsIEgyUywgTGF0Y2ljKSwgYSB0cmF2w6lzIGRlIHVuYSByZWxhY2nDs24gZnVuY2lvbmFsIGxpbmVhbCBkZWwgdGlwbyBZID0gZihYKS4NClRhbWJpw6luIHZhbW9zIGEgaW50ZW50YXIgKipwcmVkZWNpcioqIGVsIHZhbG9yIGRlIGxhIHZhcmlhYmxlIFkgcGFyYSB2YWxvcmVzIG5vIG9ic2VydmFkb3MgZGUgbGFzIHZhcmlhYmxlcyBYLg0KDQoNClRlbmVtb3MgMzAgb2JzZXJ2YWNpb25lcyBlbiBudWVzdHJvIGRhdGFzZXQuIEFob3JhIHByb2NlZGVtb3MgYSBkaXZpcmxvIGVuIGVsICpjb25qdW50byBkZSB0cmFpbiB5IHRlc3QqLiBFbCBwcmltZXJvIGxvIHV0aWxpemFyZW1vcyBwYXJhIGVudHJlbmFyIG51ZXN0cm9zIG1vZGVsb3MgeSBlbCBzZWd1bmRvIGxvIHVzYXJlbW9zIHBhcmEgY3VhbnRpZmljYXIgZWwgZXJyb3IgZGUgbG9zIG1vZGVsb3MuDQoNCg0KUGFyYSBhc2VndXJhciBxdWUgc2VhIHJlcHJvZHVjaWJsZSB1dGlsaXphbW9zIHVuYSBzZW1pbGxhLCBxdWUgcGVybWl0ZSBmaWphciBsb3MgdmFsb3JlcyBwc2V1ZG9hbGVhdG9yaW9zIG9idGVuaWRvcyBlbiBtdWNoYXMgZGUgbGFzIGZ1bmNpb25lcyB1dGlsaXphZGFzLg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgUGFyYSBhc2VndXJhciBxdWUgc2VhIHJlcHJvZHVjaWJsZSB1dGlsaXphbW9zIHVuYSBzZW1pbGxhLCBxdWUgcGVybWl0ZSBmaWphciBsb3MgdmFsb3JlcyBwc2V1ZG9hbGVhdG9yaW9zIG9idGVuaWRvcyBlbiBtdWNoYXMgZGUgbGFzIGZ1bmNpb25lcyB1dGlsaXphZGFzLg0Kc2V0LnNlZWQoMSkNCnRyYWluIDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwNCiAgICAgICAgICAgICAgICBzaXplID0gbnJvdyhjaGVkZGFyKSwNCiAgICAgICAgICAgICAgICByZXBsYWNlID0gVFJVRSwNCiAgICAgICAgICAgICAgICBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0IDwtICF0cmFpbg0KYGBgDQoNCkhhY2Vtb3MgdW4gZXN0dWRpbyBwcmVsaW1pbmFyIGRlIG51ZXN0cmFzIHZhcmlhYmxlcy4gTW9zdHJhbW9zIHVuIHNjYXR0ZXIgcGxvdCBkZSBjYWRhIHZhcmlhYmxlIGNvbnRyYXN0YWRhIGNvbiBlbCByZXN0by4gRXN0byBwZXJtaXRlIHZlciAqYSBvam8qIHNpIGFsZ8O6biBwYXIgZGUgdmFyaWFibGVzIHRpZW5lIGNvcnJlbGFjacOzbi4gIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCxmaWcud2lkdGg9NyxmaWcuaGVpZ2h0PTR9DQpwbG90KGNoZWRkYXIpDQpgYGANCiAgDQogIEFob3JhLCB1dGlsaXphbW9zIGxhIGZ1bmNpw7NuICpzdW1tYXJ5KiBkZSBSLCBsYSBjdWFsIG5vcyBwZXJtaXRlIGVzdGltYXIgYWxndW5vcyBkZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBsYSBkaXN0cmlidWNpw7NuIGRlbCBkYXRhc2V0LiBMYSBzaWd1aWVudGUgdGFibGEgbm9zIG11ZXN0cmEgbG9zIGVzdGFkw61zdGljb3MgbcOhcyBjb211bmVzOiBlbCBtw61uaW1vLCBtw6F4aW1vLCBtZWRpYW5hLCBtZWRpYSB5IGVsIDFlciB5IDNlciBjdWFydGlsLiANCg0KDQpgYGB7cixmaWcuaGVpZ2h0PTIsIGVjaG89RkFMU0UsZmlnLndpZHRoPTV9DQpzdW1tYXJ5KGNoZWRkYXIpICMgRGlzdHJpYnVjacOzbiBkZSBsYXMgdmFyaWFibGVzDQpgYGANCg0KDQpgYGB7ciBBdHRhY2gsIGluY2x1ZGU9RkFMU0V9DQphdHRhY2goY2hlZGRhcikNCmBgYA0KDQoNCkhhY2Vtb3MgbGFzIGdyw6FmaWNhcyBkZSBkaXNwZXJzacOzbiBlbnRyZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgKnRhc3RlKiB5IGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMgKkFjZXRpYywgSDJTLCBMYWN0aWMqLg0KDQpgYGB7ciBlY2hvPUZBTFNFLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9M30NCmxheW91dChtYXRyaXgoMTozLCBucm93ID0gMSkpDQojIHBsb3QgdGFzdGUgfiBBY2V0aWMNCnBsb3QoQWNldGljLCB0YXN0ZSwNCiAgICAgbWFpbiA9ICJSZWxhY2nDs24gZW50cmUgVGFzdGUgeSBBY2V0aWMiLA0KICAgICB4bGFiID0gIkFjZXRpYyIsIHlsYWIgPSAiVGFzdGUiLA0KICAgICBwY2ggPSAxOSwgZnJhbWUgPSBGQUxTRSkNCiMgcGxvdCB0YXN0ZSB+IEgyUw0KcGxvdChIMlMsIHRhc3RlLA0KICAgICBtYWluID0gIlJlbGFjacOzbiBlbnRyZSBUYXN0ZSB5IEgyUyIsDQogICAgIHhsYWIgPSAiSDJTIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KIyBwbG90IHRhc3RlIH4gTGFjdGljDQpwbG90KExhY3RpYywgdGFzdGUsDQogICAgIG1haW4gPSAiUmVsYWNpw7NubiBlbnRyZSBUYXN0ZSB5IExhY3RpYyIsDQogICAgIHhsYWIgPSAiTGFjdGljIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpsYXlvdXQobWF0cml4KDE6MSwgbnJvdyA9IDEpKQ0KYGBgDQoNClBvZGVtb3Mgb2JzZXJ2YXIgcXVlIGxhIHF1ZSBhcGVyZW50ZW1lbnRlIGd1YXJkYSB1bmEgbWVub3IgcmVsYWNpw7NuIGxpbmVhbCBjb24gdGFzdGUgZXMgbGEgdmFyaWFibGUgQWNldGljLCBlc3RlIGhlY2hvIHNlcsOhIHJlYWZpcm1hZG8gbcOhcyBhZGVsYW50ZS4NCg0KDQojIEVzdHVkaW8geSBldmFsdWFjacOzbiBkZWwgbW9kZWxvIGNvbXBsZXRvLiAgDQoNCkludGVudGFyZW1vcyBwcmVkZWNpciBsYSB2YXJpYWJsZSAqdGFzdGUqIHVzYW5kbyBlbCByZXN0byBkZSB2YXJpYWJsZXMuIFBhcmEgZW1wZXphciwgZGVmaW5pbW9zIGVsIG1vZGVsbyBjb21wbGV0bywgZWwgY3VhbCBzZSB1c2FuIHRvZGFzIGxhcyB2YXJpYWJsZXMgcGFyYSBudWVzdHJvIG1vZGVsbyBsaW5lYWwgbcO6bHRpcGxlLg0KDQokJA0KWV9pID1cYmV0YV8wICsgXGJldGFfMSB4X3tpMX0gKyBcZG90cyArIFxiZXRhX3twLTF9eF97aShwLTEpfSArIFxlcHNpbG9uX2ksXHF1YWQgaT0xLFxkb3RzLG4NCiQkDQpkb25kZSAkWV9pJCBlcyBlbCB2YWxvciBkZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgcGFyYSBlbCBpbmRpdmlkdW8gJGkkLcOpc2ltbywgDQokXGJldGFfMCQgeSBsb3MgJFxiZXRhX2okIHNvbiBsb3MgcGFyw6FtZXRyb3MgJGogPSAxLCAuLi4sIHAgLSAxJCwgDQokeF97aWp9JCBzb24gbG9zIGVsZW1lbnRvcyBkZSBsYSBtYXRyaXogZGUgbGFzIHZhcmlhYmxlcyBleHBsaWNhdGl2YXMgDQokXGVwc2lsb25faSQgZXMgZWwgdMOpcm1pbm8gZGVsIGVycm9yIGFsZWF0b3JpbyBxdWUgc3Vwb25lbW9zIHF1ZSBzZSBkaXN0cmlidXllIGNvbW8gdW5hICRcbWF0aGNhbHtOfSgwLFxzaWdtYV4yKSQsIGRvbmRlICRcc2lnbWFeMiQgZXMgbGEgdmFyaWFuemEgcXVlIHN1ZWxlIHNlciBkZXNjb25vY2lkYS4NCg0KIyMgUmVzb2x1Y2nDs24gbWVkaWFudGUgbWF0cmljZXMNCg0KVXRpbGl6YW1vcyBlbCBtw6l0b2RvIGRlIG3DrW5pbW9zIGN1YWRyYWRvcyBxdWUgZXN0aW1hIGxvcyB2YWxvcmVzICRcaGF0e1xiZXRhfSQgaW50ZW50YW5kbyBtaW5pbWl6YXIgbG9zIGVycm9yZXMgJFxlcHNpbG9uJC4gQ29tbyBoZW1vcyB2aXN0byBlbiBjbGFzZSwgbGEgZsOzcm11bGEgcXVlIHNlIGRlZHVjZSBlczoNCg0KJCQgDQpcaGF0e1xiZXRhfSA9IChYXnRYKV57LTF9WF50WQ0KJCQNCmRvbmRlICRYJCBlcyB1bmEgY29sdW1uYSBkZSAxJ3MgY29uY2F0ZW5hZGEgY29uIGxhcyB2YXJpYWJsZXMgcXVlIHVzYW1vcyBwYXJhIHByZWRlY2lyLg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KeCA8LSBtb2RlbC5tYXRyaXgoIH4gQWNldGljICsgSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhcikNCmJldGFoYXQgPC0gc29sdmUoY3Jvc3Nwcm9kKHgsIHgpLCBjcm9zc3Byb2QoeCwgdGFzdGUpKQ0KYmV0YWhhdCA8LSBjKGJldGFoYXQpDQpiZXRhaGF0DQpgYGANClBvciB0YW50bywgYXByb3hpbWFtb3MgbGFzICRcYmV0YSQgbW9kZWxvIGxpbmVhbCBjb21wbGV0byBjb24gbG9zIHZhbG9yZXMgZGUgJFxoYXR7XGJldGF9XzAsXGRvdHMsXGhhdHtcYmV0YX1fMyQgY29uIGxvcyBzaWd1aWVudGVzIHZhbG9yZXM6DQoNCiQkDQpcaGF0e1xiZXRhfV8wPS0yOC44NzY3Njk2LFxxdWFkXGhhdHtcYmV0YX1fMT0wLjMyNzc0MTMsXHF1YWRcaGF0e1xiZXRhfV8yPTMuOTExODQxLFxxdWFkXGhhdHtcYmV0YX1fMz0xOS42NzA1NDM0DQokJA0KDQojIyBSZXNvbHVjacOzbiB1c2FuZG8gbGlicmVyaWFzIGRlIFINCg0KUG9kZW1vcyB1dGlsaXphciBsYSBmdW5jacOzbiAkbG0kLCB5YSBwcm9ncmFtYWRhIGVuIFIuIERlZmluaW1vcyBlbCBtb2RlbG8gY29tcGxldG8sIHkgY29tcHJvYmFtb3MgbGFzIGJldGFzOg0KDQokJA0KdGFzdGUgXHNpbSBBY2V0aWMgXCwgKyBcLCBIMlMgXCwgKyBcLCBMYWN0aWMsIFwsICBcLCBkYXRhID0gY2hlZGRhcg0KJCQNCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KbW9kZWwuYWxsLmxtIDwtIGxtKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXIpDQoNCmZpbGFfY29lZiA8LSB2ZWN0b3IoKQ0KZGZfYW5vdmEgPC0gZGF0YS5mcmFtZSgiMSIgPSAxLCAiMiIgPSAyLCIzIiA9IDMsIjQiPTQsIHJvdy5uYW1lcyA9ICJDb2VmaWNpZW50ZXMiKQ0KY29sbmFtZXMoZGZfYW5vdmEpIDwtIGMoIkludGVyY2VwdCIsIkFjZXRpYyIsIkgyUyIsIkxhY3RpYyIpDQoNCmZvcihpIGluIDE6NCl7DQpmaWxhX2NvZWYgPC0gYyhmaWxhX2NvZWYsbW9kZWwuYWxsLmxtJGNvZWZmaWNpZW50c1tbaV1dKSAgDQp9DQoNCmRmX2Fub3ZhWzEsXSA8LSBmaWxhX2NvZWYNCmRmX2Fub3ZhDQoNCmBgYA0KDQoNCkVzdHVkaWVtb3MgcHJlbGltaW5hcm1lbnRlIHNpIGVzIHVuIG1vZGVsbyBsaW5lYWwgYWRlY3VhZG8sIHBhcmEgZWxsbyANCmNvbXByb2JhcmVtb3MgbGFzIGhpcMOzdGVzaXMgZXN0w6FuZGFyIGRlbCBtb2RlbG8gbGluZWFsIGRlIHJlZ3Jlc2nDs24gdXNhbmRvIGVsICoqdGVzdCBkZSBub3JtYWxpZGFkIFNoYXBpcm8tV2lsayoqLiBMYSBmdW5jacOzbiAkc2hhcGlyby50ZXN0JCBsZSBwYXNhbW9zIHBvciBwYXLDoW1ldHJvIGVsIHJlc2lkdW8vZXJyb3IgZGUgY2FkYSB1bmEgZGUgbGFzIG11ZXN0cmFzIHkgbm9zIGRldnVlbHZlIHVuICRwJC12YWxvci4NCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLmFsbC5sbSkpDQpgYGANCk9ic2VydmFtb3MgcXVlIGVzdGFtb3MgZW4gbGEgaGlww7N0ZXNpcyBkZSBxdWUgZWwgZXJyb3IgbnVlc3RybyBtb2RlbG8gc2UgZGlzdHJpYnV5ZSBkZSBtYW5lcmEgbm9ybWFsLCB5YSBxdWUgZWwgcC12YWxvciBlcyAkMC44ODY1ID4gMC4wNSQuIA0KDQpPdHJvIGFzcGVjdG8gcXVlIGRlYmVtb3Mgc2FiZXIgZXMgc2kgbGEgbWVkaWEgZGUgbG9zIGVycm9yZXMgc2Vyw6EgbnVsYSBvIG5vLCBwYXJhIGVsbG8gdXNhbW9zIHVuYSBmdW5jacOzbiBpbXBsZW1lbnRhZGEgZW4gUiBxdWUgbm9zIGFmaXJtYSBxdWUgZW4gbnVlc3RybyBjYXNvIGVzdG8gZXMgYXPDrS4gUmVzcGVjdG8gYSBsb3MgZXJyb3JlcyB0ZW5lbW9zIHF1ZSBzYWJlciBxdWUgc2UgZGlzdHJpYnV5ZW4gY29uIHZhcmlhbnphIGNvbnN0YW50ZSwgcXVlIGRlIG1hbmVyYSBhbsOhbG9nYSBjb21wcm9iYW1vcywgdGVuaWVuZG8gcC12YWxvcmVzIGxvIHN1ZmljaWVudGVtZW50ZSBiYWpvcyBjb21vIHBhcmEgcmVjaGF6YXIgdmFyaWFuemEgbm8gY29uc3RhbnRlLg0KIERlIGlndWFsIG1hbmVyYSB0ZW5lbW9zIHF1ZSBubyBoYXkgYXV0b2NvcnJlbGFjacOzbiBlbiBlbCBtb2RlbG8gY29tcGxldG8uDQoNClVuYSB2ZXogaGVtb3MgY29uY2x1aWRvIHF1ZSBhdW5xdWUgZXN0YW1vcyBlbiBsYXMgaGlww7N0ZXNpcyBkZSByZWdyZXNpw7NuIGxpbmVhbA0KZWwgbW9kZWxvIGNvbXBsZXRvIGEgcGVzYXIgZGUgc2VyIGVsIG3DoXMgY29tcGxlam8gcHJvYmFibGVtZW50ZSBkYSByZXN1bHRhZG9zIA0Kc2ltaWxhcmVzIGEgb3RybyBtw6FzIHNpbXBsZS4NCg0KYGBge3IgZWNobz1GQUxTRX0NCnN1bW1hcnkobW9kZWwuYWxsLmxtKQ0KYGBgDQpUcmFzIHJlYWxpemFyIGVsIHN1bW1hcnkgZGVsIG1vZGVsbywgdW5hIG9ic2VydmFjacOzbiBtdXkgaW1wb3J0YW50ZSBxdWUgc2FjYW1vcyBlcyBxdWUgZWwgcC12YWxvciBkZSBBY2V0aWMgZXMgbXV5IGdyYW5kZSAoMC45NCkgcG9yIGxvIHF1ZSBubyB2YSBhIHNlciB1bmEgdmFyaWFibGUgc2lnbmlmaWNhdGl2YSB5IHBvciB0YW50byBjb24gY2FzaSB0b2RhIHNlZ3VyaWRhZCBubyB0aWVuZSBpbXBhY3RvIHJlYWwgZW4gZWwgbW9kZWxvLg0KDQpQb3IgZWwgY29udHJhcmlvIGVsIHJlc3RvIGRlIHZhcmlhYmxlcyBzw60gc29uIHNpZ25pZmljYXRpdmFzIHBvciB0ZW5lciBwLXZhbG9yIGluZmVyaW9yIGEgMC41LCBkZXN0YWNhbmRvIExhY3RpYyBwb3IgdGVuZXIgdW4gYmV0YSBtYXlvciBxdWUgSDJTLCBsbyBxdWUgcHB1ZWRlIGhhY2Vybm9zIGxsZWdhciBhIHBlbnNhciBxdWUgY29icmUgbcOhcyBpbXBvcnRhbmNpYSBlbiB1biBtb2RlbG8gZmluYWwuDQojIyMjIENvcnJlbGFjaW9uZXMgeSB0YWJsYSBkZSByZXN1bHRhZG9zIGNvbiBlbCBlc3R1ZGlvIGRlIHN1cyBwLXZhbG9yZXMNClVzYW1vcyBlbCBwYXF1ZXRlICRHR3Bsb3QkIGRlIFIsIGVsIGN1YWwgbm9zIHBlcm1pdGUgdmlzdWFsaXphciBsYSBjb3JyZWxhY2nDs24geSBkaXNwZXJzacOzbiBlbnRyZSBsYXMgZGlzdGludGFzIHZhcmlhYmxlcy4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0zLjUsIGZpZy53aWR0aD03LCBtZXNzYWdlPUZBTFNFfQ0KY29ycGxvdCA8LSBnZ3BhaXJzKGNoZWRkYXJbdHJhaW4sXSwgcHJvZ3Jlc3M9RkFMU0UpDQpjb3JwbG90IA0KYGBgDQoNClBkZW1vcyBhcHJlY2lhciBxdWUgbGEgdmFyaWFibGUgY29uIG1lbm9yIGNvZWZlY2llbnRlIGRlIGNvcnJlbGFjacOzbiBkZSBQZWFyc29uIGVzIEFjZXRpYyxtaWVudHJhIHF1ZSBlbCByZXN0byBkZSB2YXJpYWJsZXMgdGllbmVuICB1biB2YWxvciBiYXN0YW50ZSBtYXlvci4gQ2FiZSBkZXN0YWNhciBxdWUgdG9kb3MgdGllbmVuIHVuIHNpZ25vIHBvc2l0aXZvLCBsbyBxdWUgbm9zIGRpY2UgcXVlIGVuIGdlbmVyYWwgYWwgYXVtZW50YXIgdW5hIGF1bWVudGEgbGEgb3RyYS4NCg0KDQojIyDCv1RpZW5lICpvdXRsaWVycyogbnVlc3RyYSBtdWVzdHJhPw0KDQpQYXJhIGNvbXByb2JhcmxvIGJhc3RhIHJlYWxpemFyIGVsICoqdGVzdCBkZSBCb25mZXJyb25pKiogc29icmUgbnVlc3RybyBtb2RlbG8gY29tcGxldG86DQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpvdXRsaWVyVGVzdChtb2RlbC5hbGwubG0pDQpgYGANCg0KDQpDb25jbHVpbW9zIGNvbiB1biBuaXZlbCAkXGFscGhhJCA9IDAuMDUgcXVlIG5vIHRlbmVtb3MgbmluZ8O6biBvdXRsaWVyIGVuIG51ZXN0cmEuIExvIG3DoXMgY2VyY2FubyBhIHVuICpvdXRsaWVyKiBxdWUgdGVuZW1vcyBlcyBsYSBvYnNlcnZhY2nDs24gbsO6bWVybyAxNSwgcXVlIHRpZW5lIHVuIHZhbG9yICoqQm9uZmVycm9uaSBwKiogZGUgMC4xNzQ1MyAobm8gc2UgYWNlcmNhIGEgMC4wNSkuIFBvciB0YW50bywgbm8gdGVuZW1vcyByYXpvbmVzIHBvciBsYXMgcXVlIGVsaW1pbmFyIGFsZ3VuYSBvYnNlcnZhY2nDs24gaW51c3VhbCBkZSBudWVzdHJvIGNvbmp1bnRvIGRlIGRhdG9zLiANCg0KRXN0byBzZSBwdWVkZSBjb21wcm9iYXIgZ3JhZmljYW1lbnRlIGEgdHJhdsOpcyBkZWwgc2lndWllbnRlIGdyw6FmaWNvLCBlbCBjdWFsIG1pZGUgbGEgaW5mbHVlbmNpYSBkZSBjYWRhIG9ic2VydmFjacOzbiBzb2JyZSBjYWRhIHVuYSBkZSBsYXMgYmV0YXMgZGUgbnVlc3RybyBtb2RlbG8uIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTMuNn0NCmluZmx1ZW5jZUluZGV4UGxvdChtb2RlbC5hbGwubG0pDQpgYGANCg0KVmVtb3MgcXVlIGxhIHF1ZSBtw6FzIGluZmx1eWUgZXMgbGEgYW50ZXMgbWVuY2lvbmFkYSBvYnNlcnZhY2nDs24gMTUgeSBwb3IgdGFudG8gZGViZXLDrWFtb3MgY29uc2lkZXJhciBzaSBlcyBvdXRsaWVyLiBIZW1vcyBjb21wcm9iYWRvIHF1ZSBzdWNlZGVyw61hIGFsIGVsaW1pbmFyIGVzYSBvYnNlcnZhY2nDs24gZGUgbGEgbXVlc3RyYSwgeSBzaSBiaWVuIG1lam9yYWJhIGFsZ8O6biBwLXZhbG9yIGRlIGxhcyBoaXDDs3Rlc2lzIGRlIHJlZ3Jlc2nDs24sIGVuIG90cm9zIGxvcyBlbXBlb3JhYmEsIGFzw60gcXVlIGhlbW9zIGRlY2lkaWRvIG5vIGVsaW1pbmFybGEgeSBlc3BlcmFybm9zIGEgdmVyIGVsIGNhc28gZW4gbGFzIHNlZWRzIHF1ZSBlc3R1ZGlhcmVtb3MgY29uIG3DoXMgZGV0YWxsZXMgc2kgc2FsZSBkZSBsYSBtdWVzdHJhIGNvbW8gb2JzZXJ2YWNpw7NuIGluZmx1eWVudGUuIA0KDQojIMK/Q3XDoWwgZXMgZWwgbWVqb3IgbW9kZWxvPw0KDQpDb21vIGRpY2UgZWwgKipQcmluY2lwaW8gZGUgbGEgTmF2YWphIGRlIE9ja2hhbSoqLCBhIG1lbnVkbyBsYSBleHBsaWNhY2nDs24gbcOhcyBzaW1wbGUgZXMgbGEgY29ycmVjdGEuIFF1ZXJlbW9zIHNlbGVjY2lvbmFyIHByZWRpY3RvcmVzIHF1ZSBleHBsaWNhbiBsb3MgZGF0b3MgZGUgbGEgbWFuZXJhIG3DoXMgc2ltcGxlIHBvc2libGUsIHNpbiBkaXNtaW51aXIgbGEgY2FsaWRhZCBkZSBsYXMgcHJlZGljY2lvbmVzIG11Y2hvLg0KDQojIyMgU2VwYXJhY2lvbiBkZWwgZGF0YXNldCBlbiBjb25qdW50b3MgZGUgZW50cmVuYW1pZW50byB5IHRlc3QgKDcwLTMwJSkgIA0KDQpIZW1vcyBlc2NvZ2lkbyBkaXN0aW50YXMgc2VtaWxsYXMgcGFyYSBlc3RhciBlbiBjb25kaWNpb25lcyBkZSByZWFsaXphciB1biBlc3R1ZGlvIG3DoXMgYW1wbGlvLCBlbiBsYSBlbGVjY2nDs24gZGUgbGFzIG1pc21hcyBzZSBoYSBpbnRlbnRhZG8NCmV2aXRhciBhcXVlbGxhcyBxdWUgZ2VuZXJhYmFuIG11ZXN0cmFzIGRlbWFzaWFkbyBzaW1pbGFyZXMuIExhcyBzZW1pbGxhcyB1c2FkYXMgc29uIDEsIDExMDAgeSA1IHBvc3Rlcmlvcm1lbnRlIHNlIGludHJvZHVjaXLDoW4gZG9zIG3DoXMgcGFyYSBhZmluYXIgZW4gZWwgY8OhbGN1bG8gZGUgZXJyb3Jlcy4NCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnNldC5zZWVkKDEpIA0KdHJhaW4uMSA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC4xIDwtICghdHJhaW4uMSkNCnN1bSh0ZXN0LjEpDQptb2RlbC5hbGwxIDwtIGxtKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKQ0Kc2V0LnNlZWQoMTEwMCkgDQp0cmFpbi4yIDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwgc2l6ZSA9IG5yb3coY2hlZGRhciksIHJlcGxhY2UgPSBUUlVFLCBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0LjIgPC0gKCF0cmFpbi4yKQ0Kc3VtKHRlc3QuMikNCnN1bSh0ZXN0LjE9PVRSVUUgJiB0ZXN0LjI9PVRSVUUpI3NvbG8gMSBwcmVzZWd1aW1vcw0KbW9kZWwuYWxsMiA8LSBsbSh0YXN0ZSB+IC4sIGRhdGEgPSBjaGVkZGFyW3RyYWluLjIsXSkNCnNldC5zZWVkKDUpIA0KdHJhaW4uMyA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC4zIDwtICghdHJhaW4uMykNCnN1bSh0ZXN0LjMpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC4zPT1UUlVFKQ0Kc3VtKHRlc3QuMj09VFJVRSAmIHRlc3QuMz09VFJVRSkNCm1vZGVsLmFsbDMgPC0gbG0odGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zLF0pDQpgYGANCkNvbnNpZGVyZW1vcyBsb3MgY29uanVudG9zIGRlIGVudHJlbmFtaWVudG8gcmVzdWx0YW50ZXMgZGUgbGFzIHNlbWlsbGFzOiAqdHJhaW4uMSooc2VtaWxsYSAxKSwgKnRyYWluLjIqKHNlbWlsbGEgMTEwMCksICp0cmFpbi4zKihzZW1pbGxhIDUpLlZlYWFtb3MgcXVlIG1vZGVsb3MgZGViZW1vcyBjb25zaWRlcmFyIGVuIGJhc2UgYSBudWVzdHJvcyB0cmFpbi4NCg0KIyMjIE3DqXRvZG8gQmFja3dhcmQNCg0KUGFydGltb3MgZGVsIG1vZGVsbyBjb21wbGV0byBlc3R1ZGlhZG8gZW4gbGEgc2VjY2nDs24gYW50ZXJpb3IsIGVzbyBzw60sIGV2YWx1YWRvIGVuIG51ZXN0cm9zIHJlc3BlY3Rpdm9zIHRyYWluIHkgYXBsaWNhbW9zIGNvbiAkXGFscGhhJCA9IDAuMDUsIGVsIG3DqXRvZG8gZGUgQmFja3dhcmQsIHF1ZSBjb25zaXN0ZSBlbiBlbGltaW5hciBsYSB2YXJpYWJsZSBxdWUgKm1lbm9zIGluZmx1eWEqIGEgbGEgcHJlZGljY2nDs24uIFByaW1lcm8gcmVhbGl6YW1vcyB1bmEgaXRlcmFjacOzbiBleHBsw61jaXRhIGRlbCBtw6l0b2RvIHNvYnJlIGxhIHByaW1lcmEgc2VtaWxsYSwgeSBwb3N0ZXJpb3JtZW50ZSBzZSBjb25zdHJ1eWVuIGEgdHJhdsOpcyBkZSAgbGEgbGlicmVyaWEgKm1peGxtKiBkZSBSLiANCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KIyBkcm9wMShtb2RlbC5hbGwubG0sIHRlc3QgPSAiRiIpW1s2XV0NCmZpbGFfcHZhbG9yZXMgPC0gYygwLjMzNjI3LCAwLjA0MzE4LCAwLjAyMzY1ICkNCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IDEsICIyIiA9IDIsIjMiID0gMywgcm93Lm5hbWVzID0gInAtdmFsb3IiKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJBY2V0aWMiLCJIMlMiLCJMYWN0aWMiKQ0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX3B2YWxvcmVzDQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQpFbGltaW5hbW9zIEFjZXRpYyBkZWwgbW9kZWxvIGRlYmlkbyBxdWUgc3UgcC12YWxvciBlcyA+MC4wNS4gIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQptb2RlbC5iYWNrd2FyZCA8LSB1cGRhdGUobW9kZWwuYWxsLmxtLCAuIH4gLiAtIEFjZXRpYykNCiMgZHJvcDEobW9kZWwuYmFja3dhcmQsIHRlc3QgPSAiRiIpW1s2XV0NCmZpbGFfcHZhbG9yZXMgPC0gYygwLjA1MTIyICwgMC4wMzI3NSkNCmRmX3B2YWxfZHJvcF9wMiA8LSBkYXRhLmZyYW1lKCIxIiA9IDEsICIyIiA9IDIsIHJvdy5uYW1lcyA9ICJwLXZhbG9yIikNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMikgPC0gYygiSDJTIiwiTGFjdGljIikNCmRmX3B2YWxfZHJvcF9wMlsxLF0gPC0gZmlsYV9wdmFsb3Jlcw0KZGZfcHZhbF9kcm9wX3AyDQpgYGANClJlcGV0aW1vcyBlbCBwcm9jZXNvIGNvbiBsYSB2YXJpYWJsZSBIMlMsIHlhIHF1ZSB0aWVuZSB1biBwLXZhbG9yIG1heW9yIHF1ZSAkXGFscGhhID0gMC4wNSQNCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KbW9kZWwuYmFja3dhcmQgPC0gdXBkYXRlKG1vZGVsLmJhY2t3YXJkLCAuIH4gLiAtIEgyUykNCiNkcm9wMShtb2RlbC5iYWNrd2FyZCwgdGVzdCA9ICJGIikNCmZpbGFfcHZhbG9yZXMgPC0gYygxLjM4OGUtMDUpDQpkZl9wdmFsX2Ryb3BfcDMgPC0gZGF0YS5mcmFtZSgiMSIgPSAxLCByb3cubmFtZXMgPSAicC12YWxvciIpDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDMpIDwtIGMoIkxhY3RpYyIpDQpkZl9wdmFsX2Ryb3BfcDNbMSxdIDwtIGZpbGFfcHZhbG9yZXMNCmRmX3B2YWxfZHJvcF9wMw0KYGBgDQoNCkVsIHAtdmFsb3IgZXMgbWVub3IgcXVlICRcYWxwaGEgPSAwLjA1JCwgcG9yIGxvIHF1ZSBoZW1vcyBjb25jbHVpZG8sIHlhIHF1ZSBubyB0ZW5lbW9zIHN1ZmljaWVudGUgY2VydGV6YSBwYXJhIHBvZGVyIGVsaW1pbmFyIG90cmEgdmFyaWFibGUuUG9yIHRhbnRvLCB0ZW5lbW9zIGNvbW8gcmVzdWx0YWRvIHF1ZSBsYSB2YXJpYWJsZSBxdWUgbWVqb3IgZXhwbGljYSBlbCAqdGFzdGUqIGVzICpMYWN0aWMqLiBNb2RlbG8gcmVzdWx0YW50ZTogKip0YXN0ZSAgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSoqLiAgDQoNClBvciBvdHJvIGxhZG8gbG9zIG1vZGVsb3MgYmFja3dhcmQgcmVzdWx0YW50ZXMgcG9yICptaXhsbSogc29uOiAgDQoNCioqdGFzdGUgIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0qKiB5IHBvciBvdHJvIGxhZG8gKip0YXN0ZSAgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjMsXSoqLg0KDQojIyMgTcOpdG9kbyBGb3J3YXJkIA0KDQpFbCBtw6l0b2RvIEZvcndhcmQgY29uc2lzdGUgZW4gZW1wZXphciBjb24gdW4gbW9kZWxvIGRlIHVuYSB2YXJpYWJsZSB5IHZhbW9zIGHDsWFkaWVuZG8gbGFzIHF1ZSBtw6FzIGluZmx1eWFuLCBkZXNhcnJvbGxhcmVtb3MgZWwgcHJpbWVyIG1vZGVsbyBkZSBmb3JtYSBleHBsw61jaXRhIHkgZWwgcmVzdG8gbG9zIGdlbmVyYXJlbW9zIGNvbiAqbWl4bG0qLiAgRGUgZXN0YSBtYW5lcmEgdGVuZW1vczogIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQpTQ09QRTwtKH4uK0FjZXRpYyArIEgyUyArIExhY3RpYykNCm1vZGVsLmZvcndhcmQubG0gPC0gbG0odGFzdGV+MSxkYXRhPSBjaGVkZGFyW3RyYWluLF0pDQojYWRkMShtb2RlbC5mb3J3YXJkLmxtLHNjb3BlPVNDT1BFLHRlc3Q9IkYiKVtbNl1dDQpmaWxhX3B2YWxvcmVzIDwtIGMoMS4yNTE3ODZlLTAyLCAyLjExNTQ3M2UtMDUsIDEuMzg3OTIzZS0wNSkNCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IDEsICIyIiA9IDIsIjMiID0gMywgcm93Lm5hbWVzID0gInAtdmFsb3IiKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJBY2V0aWMiLCJIMlMiLCJMYWN0aWMiKQ0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX3B2YWxvcmVzDQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KQWN0dWFsaXphbW9zIGHDsWFkaWVuZG8gTGFjdGljIHBvciB0ZW5lciBlbCBtZW5vciBwLXZhbG9yLg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KbW9kZWwuZm9yd2FyZC5sbSA8LSB1cGRhdGUobW9kZWwuZm9yd2FyZC5sbSwgLn4uICsgTGFjdGljKQ0KIyBhZGQxKG1vZGVsLmZvcndhcmQubG0sc2NvcGU9U0NPUEUsdGVzdD0iRiIpW1s2XV0NCmZpbGFfcHZhbG9yZXMgPC0gYygwLjUwMzk4Nzc0ICwwLjA1MTIxNzExNSkNCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IDEsICIyIiA9IDIsIHJvdy5uYW1lcyA9ICJwLXZhbG9yIikNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gYygiQWNldGljIiwiSDJTIikNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9wdmFsb3Jlcw0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCkNvbiBuaXZlbCBkZSBzaWduaWZpY2FjacOzbiAkXGFscGhhJCA9IDAuMDUgZXN0ZSBzZXLDrWEgbnVlc3RybyBtb2RlbG8gZmluYWwuIE1vZGVsbyByZXN1bHRhbnRlID0gKip0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKiogIA0KUG9yIG90cm8gbGFkbyBsb3MgbW9kZWxvcyBmb3J3YXJkIHJlc3VsdGFudGVzIHBvciAqbWl4bG0qIHNvbjogIA0KDQoqKnRhc3RlICB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMixdKiogeSBwb3Igb3RybyBsYWRvICoqdGFzdGUgIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zLF0qKi4NCg0KIyMgQ29uc3RydWNjacOzbiBwb3IgY3JpdGVyaW9zDQoNCkVuIGVzdGEgc3Vic2VjY2nDs24gdHJhdGFyZW1vcyBkZSBlbmNvbnRyYXIgdW4gY2FuZGlkYXRvIGEgbWVqb3IgbW9kZWxvLCBjb25zdHJ1eWVuZG8gbnVlc3Ryb3MgbW9kZWxvcyB1c2FuZG8gZGlzdGludG9zIGVuZm9xdWVzLiBUcmFzIGFwbGljYXINCmxvcyBzaWd1aWVudGVzIGNyaXRlcmlvcyBhIGxhIGhvcmEgZGVsIGRlc2Fycm9sbG8gZGUgbW9kZWxvczogJFJeMiQgYWp1c3RhZG8sIENwIGRlIE1hbGxvd3MsIENyaXRlcmlvIGRlIEluZm9ybWFjaW9uIGRlIEJheWVzIChCSUMpLCBDcml0ZXJpbyBkZSBJbmZvcm1hY2lvbiBkZSBBa2Fpa2UgKEFJQykgZWxpZ2llbmRvIGVsIHF1ZSBub3MgZGUgdW4gbWVub3IgbyBtYXlvciBjb2VmaWNpZW50ZSBzZWfDum4gZWwgbcOpdG9kbyAobG9zIGRlc2Fycm9sb3Mgc2UgcHVlZGVuIGVuY29udHJhciBlbiBlbCBzY3JpcHQpLCBsbGVnYW1vcyBhIGxhcyBzaWd1aWVudGVzIGNvbmNsdXNpb25lczogIA0Kc29sbyBhcGFyZWNlIHVuIG1vZGVsbyBudWV2byB1c2FuZG8gZWwgY3JpdGVyaW8gZGVsIGVzdGFkw61zdGljbyAkUl4yJCBwYXJhIGxhIHByaW1lcmEgc2VtaWxsYSwgKip0YXN0ZSAgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSoqLiAgDQpOb3RhbW9zIHF1ZSBsYSBjb21iaW5hY2nDs24gZGUgSDJTICsgTCBhcGFyZWNlIGVuIHRvZG9zIG51ZXN0cm9zIGNvbmp1bnRvcyBkZSBlbnRyZW5hbWllbnRvIGVuIGFsZ8O6biBtb21lbnRvLCBlcyBjYW5kaWRhdGEgYSBzZXIgbnVlc3RyYSBtZWpvciBlbGVjY2nDs24uICANCg0KQ29tcGFyYW1vcyBsb3MgbW9kZWxvcyBvYnRlbmlkb3MgaGFzdGEgYWhvcmEgZW4gc3UgcmVzcGVjdGl2YSBtdWVzdHJhIGRlIGVudHJlbmFtaWVudG8gY29uIGVsIG1vZGVsbyBjb21wbGV0byBlbiBlc2UgY29uanVudG8gZGUgZW50cmVuYW1pZW50by4NCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQptb2RlbC4xIDwtIGxtKHRhc3RlIH4gTGFjdGljLCAgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkNCm1vZGVsLjFjcml0IDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhPWNoZWRkYXJbdHJhaW4uMSxdKQ0KbW9kZWwuMiA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgIGRhdGE9Y2hlZGRhclt0cmFpbi4yLF0pDQptb2RlbC4zIDwtIGxtKHRhc3RlIH4gSDJTICtMYWN0aWMsICBkYXRhPWNoZWRkYXJbdHJhaW4uMyxdKQ0KIyBhbm92YShtb2RlbC4xLG1vZGVsLmFsbDEpW1s2XV0NCiMgYW5vdmEobW9kZWwuMWNyaXQsbW9kZWwuYWxsMSlbWzZdXQ0KIyBhbm92YShtb2RlbC4yLG1vZGVsLmFsbDIpDQojIGFub3ZhKG1vZGVsLjMsbW9kZWwuYWxsMylbWzZdXQ0KZmlsYV9wdmFsb3JlcyA8LSBjKDAuMDk4MjE0NTMsDQogICAgICAgICAgICAgICAgICAgMC4zMzYyNjg5LA0KICAgICAgICAgICAgICAgICAgIDAuOTU1MTEyMywNCiAgICAgICAgICAgICAgICAgICAwLjU1NTEyOTIpDQphbm92YShtb2RlbC4xLG1vZGVsLmFsbDEpICAgICAgICAgICAgICAgIA0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gMSwgIjIiID0gMiwiMyIgPSAzLCI0Ij0gNCwgcm93Lm5hbWVzID0gInAtdmFsb3IiKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJ0cmFpbjE6IEwgdnMgQ29tcGxldG8iLCJ0cmFpbjE6IEgyUyArIEwgdnMgQ29tcGxldG8iLCJ0cmFpbjI6IEgyUyArIEwgdnMgQ29tcGxldG8iLCAidHJhaW4xOiBIMlMrIEwgdnMgQ29tcGxldG8iKQ0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX3B2YWxvcmVzDQpkZl9wdmFsX2Ryb3BfcDEgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgDQpgYGANCg0KQ29uIGVzdG9zIHAtdmFsb3JlcyBwb2RlbW9zIGRlY2lyIHF1ZSBjb24gdW4gbml2ZWwgZGUgc2lnbmlmaWNhY2nDs24gJFxhbHBoYSQgbmluZ8O6biBtb2RlbG8gZXMgbm90YWJsZW1lbnRlIGRpZmVyZW50ZSBkZSBzdSBjb250cmFwYXJ0ZSBzYWx2byBlbiBlbCBjYXNvIGRlIGxvcyBtb2RlbG9zIHJlc3VsdGFudGVzIGVuICp0cmFpbjIqIGVzdG8gcHVlZGUgc2VyIHBvciBsYSBjYW50aWRhZCBkZSBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIHByZXNlbnRlcyBlbiBsYSBtdWVzdHJhLCBsbyB0cmF0YXJlbW9zIGVuIGxhIHNpZ3VpZW50ZSBzZWNjacOzbi4gIA0KDQojIERpYWdub3N0aWNvOiBDb21wcm9iYWNpb25lcyBkZSBoaXBvdGVzaXMsIG91dGxpZXJzIHkgb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcw0KDQpFbiBlc3RhIHNlY2Npw7NuIGVzdHVkaWFyZW1vcyBzaSBudWVzdHJvcyBtb2RlbG9zIGN1bXBsZW4gbGFzIGNvbmRpY2lvbmVzDQpuZWNlc2FyaWFzIGRlIHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4gIA0KDQpOdWVzdHJvIGVuZm9xdWUgY29uc2lzdGlyw6EgZW4gdW4gYW7DoWxpc2lzIGdyw6FmaWNvLCBhY29tcGHDsWFkbyBkZSB0ZXN0cw0KZXN0YWTDrXN0aWNvcyBlbiBsb3MgY2Fzb3MgZW4gbG9zIHF1ZSBzZSBhcHJlY2llIHVuYSBkaXNjcmVwYW5jaWEgbm90YWJsZS4NCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmF0dGFjaChjaGVkZGFyKQ0KYGBgDQoNCiMjIMK/U29uIG51ZXN0cm9zICptb2RlbG9zKiwgbW9kZWxvcyBkZSByZWdyZXNpw7NuIGxpbmVhbD86IENvbXByb2JhY2nDs24gZGUgaGlww7N0ZXNpcy4NCg0KRW4gbGEgc2VjY2nDs24gMyBzZSB0b21hIHVuIGVuZm9xdWUgKm5hw692ZSogYSBsYSBob3JhIGRlIGNvbnN0cnVpciBsb3MgbW9kZWxvcywNCnlhIHF1ZSBubyBoZW1vcyBlc3R1ZGlhZG8gc2kgaGF5IG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMsIHBvZHLDrWFtb3MgdGVuZXIgdW5hDQptdWVzdHJhIHF1ZSBubyBlcyBsYSBhZGVjdWFkYSBwYXJhIGVsIGVzdHVkaW8gZGUgbnVlc3Ryb3MgZGF0b3MuICANCg0KVW4gbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsIGRlYmUgc2F0aXNmYWNlciBsYXMgc2lndWllbnRlcyBoaXDDs3Rlc2lzIGNvbiBuaXZlbCANCmRlIHNpZ25pZmljYWNpw7NuICRcYWxwaGEkIGFkZWN1YWRvOg0KDQoxLiBMb3MgZXJyb3JlcyBcKFxlcHNpbG9uX3tpfVwpIHRpZW5lbiBkaXN0cmlidWNpw7NuIG5vcm1hbC4gIA0KMi4gTG9zIGVycm9yZXMgXChcZXBzaWxvbl97aX1cKSB0aWVuZW4gbWVkaWEgY2Vyby4gIA0KMy4gTG9zIGVycm9yZXMgXChcZXBzaWxvbl97aX1cKSB0aWVuZW4gdmFyaWFuemEgY29uc3RhbnRlLiAgDQo0LiBMb3MgZXJyb3JlcyBcKFxlcHNpbG9uX3tpfVwpIG5vIGVzdMOhbiBjb3JyZWxhY2lvbmFkb3MuICANCg0KYGBge3IgaW5jbHVkZT1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KYWxmYW4gPC0gMC4wNQ0KZmlsYV9saW5lYWxpZGFkIDwtIGMocm91bmQocmVzZXR0ZXN0KG1vZGVsLjEsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJlc2V0dGVzdChtb2RlbC4xY3JpdCwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMSxdKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQocmVzZXR0ZXN0KG1vZGVsLjIsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjIsXSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJlc2V0dGVzdChtb2RlbC4zLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4zLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICBhbGZhbiwiUmVzZXR0ZXN0IikNCmZpbGFfbm9ybWFsaWRhZCA8LSBjKHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xKSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xY3JpdCkpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMikpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMykpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICBhbGZhbiwgIlRlc3QgU2hhcGlybyBXaWxrIikNCmZpbGFfbWVkaWFPIDwtIGModC50ZXN0KHJlc2lkKG1vZGVsLjEpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgIHQudGVzdChyZXNpZChtb2RlbC4xY3JpdCksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgdC50ZXN0KHJlc2lkKG1vZGVsLjIpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgIHQudGVzdChyZXNpZChtb2RlbC4zKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlLA0KICAgICAgICAgICAgICAgICBhbGZhbiwgInQtdGVzdCIpDQpmaWxhX3Zhcl9jdGUgPC0gYyhyb3VuZChuY3ZUZXN0KG1vZGVsLjEpJHAsMyksDQogICAgICAgICAgICAgICAgICByb3VuZChuY3ZUZXN0KG1vZGVsLjFjcml0KSRwLDMpLA0KICAgICAgICAgICAgICAgICAgcm91bmQobmN2VGVzdChtb2RlbC4yKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgcm91bmQobmN2VGVzdChtb2RlbC4zKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgYWxmYW4sICJUZXN0IG5jdiIpDQogICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgIA0KZmlsYV9jb3JyIDwtIGMoZHVyYmluV2F0c29uVGVzdChtb2RlbC4xKSRwLA0KICAgICAgICAgICAgICAgZHVyYmluV2F0c29uVGVzdChtb2RlbC4xY3JpdCkkcCwNCiAgICAgICAgICAgICAgIGR1cmJpbldhdHNvblRlc3QobW9kZWwuMikkcCwNCiAgICAgICAgICAgICAgIGR1cmJpbldhdHNvblRlc3QobW9kZWwuMykkcCwNCiAgICAgICAgICAgICAgIGFsZmFuLCJUZXN0IGRlIER1cmJpbi1XYXRzb24iKQ0KIA0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsNSksIjIiID0gcmVwKDAsNSksIjMiID0gcmVwKDAsNSksIjQiPSByZXAoMCw1KSwgIjUiPSByZXAoMCw1KSwgIjYiID0gcmVwKDAsNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9YygiTGluZWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWVkaWEgPSAwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWYXJpYW56YSBjb25zdGFudGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvcnJlbGFjacOzbiIpKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSAgICBjKCJ0cmFpbjE6IEwiLCJ0cmFpbjE6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjI6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjM6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOaXZlbCBkZSBzaWdpbmlmaWNhY2nDs24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUZXN0IHV0aWxpemFkbyIpDQoNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9saW5lYWxpZGFkDQpkZl9wdmFsX2Ryb3BfcDFbMixdIDwtIGZpbGFfbm9ybWFsaWRhZA0KZGZfcHZhbF9kcm9wX3AxWzMsXSA8LSBmaWxhX21lZGlhTw0KZGZfcHZhbF9kcm9wX3AxWzQsXSA8LSBmaWxhX3Zhcl9jdGUNCmRmX3B2YWxfZHJvcF9wMVs1LF0gPC0gZmlsYV9jb3JyDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQoNClBvZGVtb3Mgb2JzZXJ2YXIgcXVlIHNlIHZlcmlmaWNhbiBhIG5pdmVsIGRlIHNpZ25pZmljYWNpw7NuICRcYWxwaGEkID0gMC4wNSBzZSB2ZXJpZmljYW4gdG9kYXMgbGFzIGhpcMOzdGVzaXMgZGUgbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsLiBFbiBsYXMgc2lndWllbnRlcyBncsOhZmljYXMgcG9kZW1vcyBvYnNlcnZhciBjb21vIGxvcyByZXNpZHVvcyBkZSBsb3MgbW9kZWxvcyAqKnRhc3RlIH4gSDJTICsgTCoqIGRlIGxvcyBjb25qdW50b3MgKnRyYWluMiogeSAqdHJhaW4zKiBzZSBjb21wb3J0YW4gbWVqb3IgcXVlIGN1YWxxdWllcmEgZGUgbG9zIG1vZGVsb3MgcHJvcHVlc3RvcyBlbiBsYSBtdWVzdHJhICp0cmFpbjEqDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTZ9DQpwYXIobWZyb3c9YygxLDIpKQ0KcXFub3JtKHJlc2lkKG1vZGVsLjEpKQ0KcXFsaW5lKHJlc2lkKG1vZGVsLjEpKQ0KDQpxcW5vcm0ocmVzaWQobW9kZWwuMWNyaXQpKQ0KcXFsaW5lKHJlc2lkKG1vZGVsLjFjcml0KSkNCg0KYGBgDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD02fQ0KcGFyKG1mcm93PWMoMSwyKSkNCnFxbm9ybShyZXNpZChtb2RlbC4yKSkNCnFxbGluZShyZXNpZChtb2RlbC4yKSkNCg0KcXFub3JtKHJlc2lkKG1vZGVsLjMpKQ0KcXFsaW5lKHJlc2lkKG1vZGVsLjMpKQ0KDQpgYGANCg0KDQpQb3N0ZXJpb3JtZW50ZSwgcmVhbGl6YW1vcyB1biBlc3R1ZGlvIGRlIGxhIGNvbGluZWFsaWRhZC4gUGFyYSBlbGxvLCBvYnNlcnZhbW9zIHF1ZSBlbCBtb2RlbG8gKip0YXN0ZSB+IExhY3RpYyAsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0qKiBzb2xvIHRpZW5lIHVuIHByZWRpY3RvciBsdWVnbyBubyBoYXkgcHJlc2VudGUgbmluZ8O6biB0aXBvIGNvbGluZWFsaWRhZC4NCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KIyB2aWYobW9kZWwuMSkgZGlqaW1vcyBxdWUgZWwgZGUgbGFjdGljIG5vIHBvcnF1ZSBzdWNlZGUgZXN0byBubyBoYXkgY29saW4gcG9yIHNvbG8gMSB2YXINCiMgdmlmKG1vZGVsLjFjcml0KQ0KIyB2aWYobW9kZWwuMikNCiMgdmlmKG1vZGVsLjMpICMgbG9zIHZhbG9yZXMgZGUgVklGIG5vIGluZGljYW4gY29saW5lYWxpZGFkIGdyYXZlDQoNCg0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsNCksIjIiID0gcmVwKDAsNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPWMoInRyYWluMTogTCIsInRyYWluMTogSDJTICsgTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRyYWluMjogSDJTICsgTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRyYWluMzogSDJTICsgTCIpKQ0KDQpmaWxhX2MxIDwtIGMoIlNvbG8gdGllbmUgdW4gcHJlZGljdG9yIiwiU29sbyB0aWVuZSB1biBwcmVkaWN0b3IiKQ0KZmlsYV9jMiA8LSBjKHZpZihtb2RlbC4xY3JpdClbWzFdXSx2aWYobW9kZWwuMWNyaXQpW1syXV0pDQpmaWxhX2MzIDwtIGModmlmKG1vZGVsLjIpW1sxXV0sdmlmKG1vZGVsLjIpW1syXV0pDQpmaWxhX2M0IDwtIGModmlmKG1vZGVsLjMpW1sxXV0sdmlmKG1vZGVsLjMpW1syXV0pDQoNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9jMQ0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBmaWxhX2MyDQpkZl9wdmFsX2Ryb3BfcDFbMyxdIDwtIGZpbGFfYzMNCmRmX3B2YWxfZHJvcF9wMVs0LF0gPC0gZmlsYV9jNA0KDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDEpIDwtIGMoIkgyUyIsIkxhY3RpYyIpDQpkZl9wdmFsX2Ryb3BfcDENCg0KYGBgDQoNCk51ZXN0cm9zIHZhbG9yZXMgc29uIG11eSBidWVub3MsIGVudGVuZGllbmRvIHBvciBidWVubyBWSUYgPCAxMCwgcG9yIGxvIHRhbnRvIG5vIHRlbmVuZW1vcyBxdWUgcHJlb2N1cGFybm9zIGRlIHVuYSBjb2xpbmVhbGlkYWQgZ3JhdmUgZW50cmUgbGFzIHZhcmlhYmxlcy4NCg0KDQojIyBFc3R1ZGlvIGRlIG91dGxpZXJzDQoNCkEgZmluIGRlIG9idGVuZXIgZGlzdGludG9zIHB1bnRvcyBkZSB2aXN0YSB1dGlsaXphcmVtb3MgZG9zIG3DqXRvZG9zLCB1biB2YWxvciBkZSBCb25mZXJyb25pIGVuIHVuIGVzdGFkw61zdGljbyAkdF97MS1cZnJhY3tcYWxwaGF9ezJufTtuLXAtMX0kIHkgbGEgZnVuY2nDs24gKm91dGxpZXJUZXN0KiBxdWUgdXRpbGl6YSBwLXZhbG9yZXMgZGUgQm9uZmVycm9uaSBvYnRlbmlkb3MgYSB0cmF2w6lzIGRlIHQtdGVzdHMuICANCg0KRW4gbG9zIGN1YXRybyBtb2RlbG9zIHkgYmFqbyBsb3MgZG9zIGNyaXRlcmlvcyBubyBzZSBvYnRpZW5lIG5pbmd1bmEgb2JzZXJ2YWNpw7NuIHF1ZSBzZSBwdWVkYSBhY2VwdGFyIGNvbW8gKm91dGxpZXIqIGEgbml2ZWwgZGUgc2lnbmlmaWNhY2nDs24gJFxhbHBoYSQgPSAwLjA1DQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpzaWduaSA8LSAwLjA1DQoNCm4xPC1ucm93KGNoZWRkYXJbdHJhaW4uMSxdKQ0KcDEgPC1ucm93KHN1bW1hcnkobW9kZWwuMSkkY29lZikNCg0KDQpuMWNyaXQ8LW5yb3coY2hlZGRhclt0cmFpbi4xLF0pDQpwMWNyaXQgPC1ucm93KHN1bW1hcnkobW9kZWwuMWNyaXQpJGNvZWYpDQoNCm4yPC1ucm93KGNoZWRkYXJbdHJhaW4uMixdKQ0KcDIgPC1ucm93KHN1bW1hcnkobW9kZWwuMikkY29lZikNCg0KbjM8LW5yb3coY2hlZGRhclt0cmFpbi4zLF0pDQpwMyA8LW5yb3coc3VtbWFyeShtb2RlbC4zKSRjb2VmKQ0KDQpCQ1YxIDwtIHF0KDEgLSBzaWduaSAvICgyICogbjEpLCBuMS1wMS0xKSANCkJDVjFjcml0IDwtIHF0KDEgLSBzaWduaSAvICgyICogbjFjcml0KSwgbjFjcml0LXAxY3JpdC0xKSANCkJDVjIgPC0gcXQoMSAtIHNpZ25pIC8gKDIgKiBuMiksIG4yLXAyLTEpIA0KQkNWMyA8LSBxdCgxIC0gc2lnbmkgLyAoMiAqIG4zKSwgbjMtcDMtMSkgDQoNCnN1bShhYnMocnN0dWRlbnQobW9kZWwuMSkpID4gQkNWMSkNCnN1bShhYnMocnN0dWRlbnQobW9kZWwuMWNyaXQpKSA+IEJDVjFjcml0KQ0Kc3VtKGFicyhyc3R1ZGVudChtb2RlbC4yKSkgPiBCQ1YyKQ0Kc3VtKGFicyhyc3R1ZGVudChtb2RlbC4zKSkgPiBCQ1YzKQ0KDQoNCm91dGxpZXJUZXN0KG1vZGVsLjEpDQpvdXRsaWVyVGVzdChtb2RlbC4xY3JpdCkjTkE/DQpvdXRsaWVyVGVzdChtb2RlbC4yKSAjIG5vIGhheSBlbiBuaW5ndW5vIGRlIGxvcyBkb3MgbW9kZWxvcyBwbGFudGVhZG9zDQpvdXRsaWVyVGVzdChtb2RlbC4zKQ0KDQpgYGANCiMjIEVzdHVkaW8gZGUgb2JzZXJ2YWNpb25lcyBJbmZsdXllbnRlcw0KDQpBbCBpZ3VhbCBxdWUgZW4gbGEgYW50ZXJpb3Igc2VjY2nDs24gYSBmaW4gZGUgcG9kZXIgZW5jb250cmFyIGVsIGNyaXRlcmlvIHF1ZSBtZWpvciBzZSBhanVzdGUgYSBudWVzdHJvIG1vZGVsbywgZW4gZWwgcXVlIGhheSBxdWUgdGVuZXIgZW4gY3VlbnRhIHF1ZSBlcyB1bmEgbXVlc3RyYSBkZSB0YW1hw7FvIHJlZHVjaWRvLCB1dGlsaXphcmVtb3MgdmFyaW9zIGNyaXRlcmlvcywgYWRlbcOhcyBkZSBkaXN0aW50YXMgdMOpY25pY2FzIGdyw6FmaWNhcy4gTG9zIGNyaXRlcmlvcyB1c2Fkb3Mgc2Vyw6FuOiAgDQoxLkNyaXRlcmlvIDE6IHZhbG9yZXMgbGV2ZXJhZ2UgKGhpaSkgbWF5b3JlcyBxdWUgJFxmcmFjezJwfXtufSQuICANCjIuQ3JpdGVyaW8gMjogdmFsb3JlcyB8REZGSVRTfCBzb24gbWF5b3JlcyBxdWUgJDIgXGNkb3QgXHNxcnR7XGZyYWN7MnB9e259fSQuICANCg0KMy5Dcml0ZXJpbyAzOiB2YWxvcmVzIHxERkJFVEFTfCBtYXlvcmVzIHF1ZSAkMiBcY2RvdCBcc3FydHtcZnJhY3sycH17bn19JC4gIA0KDQo0LkNyaXRlcmlvIDQ6ICpJbmZsdWVuY2VQbG90Ki4NCg0KRW4gbGEgc2lndWllbnRlIHRhYmxhIG9ic2VydmFtb3MgbGFzIG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMgb2J0ZW5pZGFzIHBvciBjYWRhIGNyaXRlcmlvLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQoNCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IHJlcCgwLDQpLCIyIiA9IHJlcCgwLDQpLCIzIiA9IHJlcCgwLDQpLCI0IiA9IHJlcCgwLDQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID1jKCJ0cmFpbjE6IEwiLCJ0cmFpbjE6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjI6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjM6IEgyUyArIEwiKSkNCg0KZmlsYV9jMSA8LSBjKCIxLDUsMTYsMjMsMjQsMjYiLCAiMSwxMiwyNCIsIjEsMyw1LDgsOSwxMiwxMywxNCwxNiwxOSwyMywyNCwyNywyOCwzMCIsIjEsMTIsMjQiKQ0KZmlsYV9jMiA8LSBjKCIyMyIsICIxMiIsICIxLDMsOCw5LDExLDEyLDEzLDE0LDE5LDIzLDI0LDI2LDI3LDI4LDMwIiwiMSw4LDEyLDIzIikNCmZpbGFfYzMgPC0gYygiNiIsIk5pbmd1bm8iICwgIjEsMyw0LDcsOCw5LDExLDEyLDE2LDE3LDIwLDI5LDMwIiwiMSw2LDcsOCwxNSIpDQpmaWxhX2M0IDwtIGMoIk5pbmd1bm8iLCJOaW5ndW5vIiwiMSw0LDUsNywxMiwxNCwxNiwxNywxOSwyMywyNywyOSIsIjEsNywxNSwxOSwyNCIpDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDEpIDwtIGMoIkNyaXRlcmlvIDEiLCJDcml0ZXJpbyAyIiwiQ3JpdGVyaW8gMyIsIkNyaXRlcmlvIDQiKQ0KDQpkZl9wdmFsX2Ryb3BfcDFbMSxdIDwtIGZpbGFfYzENCmRmX3B2YWxfZHJvcF9wMVsyLF0gPC0gZmlsYV9jMg0KZGZfcHZhbF9kcm9wX3AxWzMsXSA8LSBmaWxhX2MzDQpkZl9wdmFsX2Ryb3BfcDFbNCxdIDwtIGZpbGFfYzQNCmRmX3B2YWxfZHJvcF9wMQ0KYGBgDQoNClRvbWFtb3MgbGEgZGVjaXNpw7NuIGRlIGVsZWdpciBsb3MgZWxlbWVudG9zIHF1ZSBzZSByZXBpdGFuIGVuIHZhcmlvcyB5YSBxdWUgc2kgZWxpbWluw6FzZW1vcyBsb3MgZGVsIGNyaXRlcmlvIDMgZWwgcmVzdWx0YWRvIHNlcsOtYSBkZW1hc2lhZG8gcGVxdWXDsW8gcGFyYSBzZXIgYXB0byBwYXJhIGxhIHJlZ3Jlc2nDs24gbGluZWFsLiBOdWVzdHJvIGNyaXRlcmlvIGEgc2VndWlyIGVzIHF1ZSBlc3TDqW4gZW4gYWwgbWVub3MgZG9zIGNyaXRlcmlvcyAgZGUgbG9zIHJlc3RhbnRlcy4NCg0KYGBge3IgZWNobz1GQUxTRX0NCg0KcGFyKG1mcm93PWMoMiwyKSkNCnAxIDwtIGluZmx1ZW5jZVBsb3QobW9kZWwuMSkNCnBvc19pbmZsdXllbnRlc18xIDwtIGMoMSwxMiwyNCkNCg0KcDIgPC1pbmZsdWVuY2VQbG90KG1vZGVsLjFjcml0KQ0KcG9zX2luZmx1eWVudGVzXzFjcml0IDwtIGMoMSw4LDEyLDIzKQ0KDQpwMyA8LWluZmx1ZW5jZVBsb3QobW9kZWwuMikNCnBvc19pbmZsdXllbnRlc18yIDwtIGMoMSw2LDcsOCwxNSkNCg0KDQpwNCA8LWluZmx1ZW5jZVBsb3QobW9kZWwuMykNCnBvc19pbmZsdXllbnRlc18zIDwtIGMoMSw3LDE1LDE5LDI0KQ0KDQpgYGANCg0KRXN0YXMgb2JzZXJ2YWNpb25lcyBzb24gbGFzIHByZXNlbnRlcyBlbiBsYSBjdWFydGEgY29sdW1uYSBkZSBsYSB0YWJsYSB5IGVuIGdlbmVyYWwgc29uIGVuIGxhcyBwcmltZXJhcyBlbiBsYXMgcXVlIG5vcyBmaWplbW9zIGEgbGEgaG9yYSBkZSB2ZXIgc2kgbGFzIHRvbWFtb3MgY29tbyBpbmZsdXllbnRlcyBvIG5vLg0KDQpCYWpvIG51ZXN0cm8gY3JpdGVyaW8gcXVlZGFyw61hbiBjb21vIHBvc2libGVzIGluZmx1eWVudGVzIGxhcyBzaWd1aWVudGVzIG9ic2VydmFjaW9uZXM6DQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9cmVwKDAsNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPWMoInRyYWluMTogTCIsInRyYWluMTogSDJTICsgTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRyYWluMjogSDJTICsgTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRyYWluMzogSDJTICsgTCIpKQ0KDQpmaWxhX2MxIDwtIGMoIjEsMTIiKQ0KZmlsYV9jMiA8LSBjKCIxLDEyLDIzIikNCmZpbGFfYzMgPC0gYygiMiw2IikNCmZpbGFfYzQgPC0gYygiTm8gc2UgcmVwaXRlIG5pbmd1bm8iKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJPYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIikNCg0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX2MxDQpkZl9wdmFsX2Ryb3BfcDFbMixdIDwtIGZpbGFfYzINCmRmX3B2YWxfZHJvcF9wMVszLF0gPC0gZmlsYV9jMw0KZGZfcHZhbF9kcm9wX3AxWzQsXSA8LSBmaWxhX2M0DQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQoNCkFob3JhIGVzIGN1YW5kbyB0ZW5lbW9zIHF1ZSBkZXRlcm1pbmFyIHNpIHZhbiBhIHNlciBpbmZsdXllbnRlcyBvIG5vLCBlc3RvIGxvIHZlcmVtb3MgY29tcGFyYW5kbyBsb3MgbW9kZWxvcyBjb24gbGFzIG11ZXN0cmFzIGRlIGVudHJlbmFtaWVudG8gc2luIGVsaW1pbmFyIGluZmx1eWVudGVzIHkgY29uIGxhcyBtdWVzdHJhcyBtb2RpZmljYWRhcywgeSBldmFsdWFyIHNpIG1lam9yYW4gbyBlbXBlb3JhbiBsb3MgcC12YWxvcmVzIGRlIGxhcyBoaXDDs3Rlc2lzIGRlIGxvcyBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24uDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpwb3NfMTwtYyhUUlVFLHJlcChGQUxTRSwxMCksVFJVRSxyZXAoRkFMU0UsMTgpKQ0KdHJhaW4uMWluZjwtdHJhaW4uMSYhcG9zXzENCm1vZGVsLjFpbmY8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMWluZixdKQ0KYGBgDQojIyMgdGFzdGUgfiAgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSB2cyB0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMWluZixdDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQoNCmZpbGFfbGluZWFsaWRhZCA8LSBjKHJvdW5kKHJlc2V0dGVzdChtb2RlbC4xLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChyZXNldHRlc3QobW9kZWwuMWluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMWluZixdKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgIlJlc2V0dGVzdCIpDQoNCg0KZmlsYV9ub3JtYWxpZGFkIDwtIGMocm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjEpKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjFjcml0KSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgICJUZXN0IFNoYXBpcm8gV2lsayIpDQpmaWxhX21lZGlhTyA8LSBjKHQudGVzdChyZXNpZChtb2RlbC4xKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlLA0KICAgICAgICAgICAgICAgICB0LnRlc3QocmVzaWQobW9kZWwuMWluZiksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgInQtdGVzdCIpDQpmaWxhX3Zhcl9jdGUgPC0gYyhyb3VuZChuY3ZUZXN0KG1vZGVsLjEpJHAsMyksDQogICAgICAgICAgICAgICAgICByb3VuZChuY3ZUZXN0KG1vZGVsLjFpbmYpJHAsMyksDQogICAgICAgICAgICAgICAgICAiVGVzdCBuY3YiKQ0KICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICANCmZpbGFfY29yciA8LSBjKGR1cmJpbldhdHNvblRlc3QobW9kZWwuMSkkcCwNCiAgICAgICAgICAgICAgIGR1cmJpbldhdHNvblRlc3QobW9kZWwuMWluZikkcCwNCiAgICAgICAgICAgICAgICJUZXN0IGRlIER1cmJpbi1XYXRzb24iKQ0KIA0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsNSksIjIiID0gcmVwKDAsNSksIjMiID0gcmVwKDAsNSkscm93Lm5hbWVzID1jKCJMaW5lYWxpZGFkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhID0gMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZhcmlhbnphIGNvbnN0YW50ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvcnJlbGFjacOzbiIpKQ0KDQoNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gICAgYygidHJhaW4xOiBMIiwidHJhaW4xOiBMLCBzaW4gaW5mbHV5ZW50ZXMiLCAiVGVzdCB1dGlsaXphZG8iKQ0KDQpkZl9wdmFsX2Ryb3BfcDFbMSxdIDwtIGZpbGFfbGluZWFsaWRhZA0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBmaWxhX25vcm1hbGlkYWQNCmRmX3B2YWxfZHJvcF9wMVszLF0gPC0gZmlsYV9tZWRpYU8NCmRmX3B2YWxfZHJvcF9wMVs0LF0gPC0gZmlsYV92YXJfY3RlDQpkZl9wdmFsX2Ryb3BfcDFbNSxdIDwtIGZpbGFfY29ycg0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCk51ZXN0cmFzIGhpcMOzdGVzaXMgZGVsIG1vZGVsbyBsaW5lYWwgc2UgdmVuIG5vdGFibGVtZW50ZSBtZWpvcmFkYXMsIHRlbmVtb3MgdW5hIGRpc3RyaWJ1Y2nDs24gbcOhcyBwYXJlY2lkYSBhIHVuYSBub3JtYWwsIG1lam9yIGRpc3RyaWJ1aWRhIGVuIHRvcm5vIGEgdW5hIGxpbmVhbC4gIA0KUmVhbGl6YW1vcyB1biBwZXF1ZcOxbyBpbnRlcmNhbWJpbyBlbiBlbCBxdWUgbnVlc3RyYSB2YXJpYW56YSBwYXJlY2UgbWVub3MgY29uc3RhbnRlIHBlcm8gc2UgbWFudGllbmUgcG9yIGVuY2ltYSBkZSB0b2RvcyBsb3Mgbml2ZWxlcyBkZSBzaWduaWZpY2FjacOzbiBoYWJpdHVhbGVzLiAgDQpUb21hbW9zIGxhIGRlY2lzacOzbiBkZSBhY3R1YWxpemFyICpjaGVkZGFyW3RyYWluLjEsXSogY29uICAqY2hlZGRhclt0cmFpbmluZi4xLF0qLCBxdWUgZXMgbGEgdmVyc2nDs24gc2luIG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMuDQojIyMgdGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSB2cyB0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMWNyaXRpbmYsXQ0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnRyYWluLjFhdXg8LXRyYWluLjENCnRyYWluLjE8LXRyYWluLjFpbmYNCm1vZGVsLjE8LW1vZGVsLjFpbmYNCmBgYA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KcG9zXzFjcml0PC1jKFRSVUUscmVwKEZBTFNFLDEwKSxUUlVFLHJlcChGQUxTRSwxMCksVFJVRSxyZXAoRkFMU0UsNykpDQoNCnRyYWluLjFjcml0aW5mPC10cmFpbi4xYXV4JiFwb3NfMWNyaXQNCm1vZGVsLjFjcml0aW5mPC0gbG0odGFzdGUgfkgyUytMYWN0aWMgLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xY3JpdGluZixdKQ0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCg0KZmlsYV9saW5lYWxpZGFkIDwtIGMocm91bmQocmVzZXR0ZXN0KG1vZGVsLjFjcml0LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChyZXNldHRlc3QobW9kZWwuMWNyaXRpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjFjcml0aW5mLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICAiUmVzZXR0ZXN0IikNCg0KDQpmaWxhX25vcm1hbGlkYWQgPC0gYyhyb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMWNyaXQpKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjFjcml0aW5mKSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgICJUZXN0IFNoYXBpcm8gV2lsayIpDQpmaWxhX21lZGlhTyA8LSBjKHQudGVzdChyZXNpZChtb2RlbC4xY3JpdCksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgdC50ZXN0KHJlc2lkKG1vZGVsLjFjcml0aW5mKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlLA0KICAgICAgICAgICAgICAgICAidC10ZXN0IikNCmZpbGFfdmFyX2N0ZSA8LSBjKHJvdW5kKG5jdlRlc3QobW9kZWwuMWNyaXQpJHAsMyksDQogICAgICAgICAgICAgICAgICByb3VuZChuY3ZUZXN0KG1vZGVsLjFjcml0aW5mKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgIlRlc3QgbmN2IikNCiAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgDQpmaWxhX2NvcnIgPC0gYyhkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjFjcml0KSRwLA0KICAgICAgICAgICAgICAgZHVyYmluV2F0c29uVGVzdChtb2RlbC4xY3JpdGluZikkcCwNCiAgICAgICAgICAgICAgICJUZXN0IGRlIER1cmJpbi1XYXRzb24iKQ0KIA0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsNSksIjIiID0gcmVwKDAsNSksIjMiID0gcmVwKDAsNSkscm93Lm5hbWVzID1jKCJMaW5lYWxpZGFkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhID0gMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZhcmlhbnphIGNvbnN0YW50ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvcnJlbGFjacOzbiIpKQ0KDQoNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gICAgYygidHJhaW4xOiBIMlMgKyBMIiwidHJhaW4xOiBIMlMgKyBMLCBzaW4gaW5mbHV5ZW50ZXMiLCAiVGVzdCB1dGlsaXphZG8iKQ0KDQpkZl9wdmFsX2Ryb3BfcDFbMSxdIDwtIGZpbGFfbGluZWFsaWRhZA0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBmaWxhX25vcm1hbGlkYWQNCmRmX3B2YWxfZHJvcF9wMVszLF0gPC0gZmlsYV9tZWRpYU8NCmRmX3B2YWxfZHJvcF9wMVs0LF0gPC0gZmlsYV92YXJfY3RlDQpkZl9wdmFsX2Ryb3BfcDFbNSxdIDwtIGZpbGFfY29ycg0KDQoNCg0KDQpkZl9wdmFsX2Ryb3BfcDENCg0KDQpgYGANCkVzdGUgZXMgdW4gY2FzbyB1biB0YW50byBwYXJ0aWN1bGFyLCB0ZW5lbW9zIHVub3MgZGF0b3MgcGVyZmVjdGFtZW50ZSBkaXN0cmlidWlkb3MsIHBlcm8geWEgbG8gZXN0YWJhbiBhbnRlcyBwcmFjdGljYW1lbnRlLiBBIGNhbWJpbyBkZSBlc28gcGVyZGVtb3MgdW4gY2llcnRvIGdyYWRvIGRlIGxpbmVhbGlkYWQgcXVlIGhheSBxdWUgdGVuZXIgZW4gY3VlbnRhLCBlbiBlc3RlIGNhc28gbm8gaGF5IHVuYSBkaWZlcmVuY2lhIHRhbiBub3RhYmxlIGNvbiBlbCBtb2RlbG8gY29tbyBlbiBxdWUgc29sbyBpbmNvcnBvcmFiYSBhIExhY3RpYy4gIA0KDQpUb21hbW9zIGxhIGRlY2lzacOzbiBkZSBhY3R1YWxpemFyICpjaGVkZGFyW3RyYWluLjFjcml0LF0qIGNvbiAgKmNoZWRkYXJbdHJhaW4uMWNyaXRpbmYsXSosIHF1ZSBlcyBsYSB2ZXJzacOzbiBzaW4gb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcy4NCg0KIyMjIHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0gdnMgdGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjJpbmYsXQ0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnRyYWluLjFjcml0PC10cmFpbi4xY3JpdGluZg0KbW9kZWwuMWNyaXQ8LSBtb2RlbC4xY3JpdGluZg0KYGBgDQoNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnBvc18yPC1jKHJlcChGQUxTRSw1KSxUUlVFLHJlcChGQUxTRSwyNCkpDQoNCnRyYWluLjJpbmY8LXRyYWluLjImIXBvc18yDQptb2RlbC4yaW5mPC0gbG0odGFzdGUgfiBIMlMrTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yaW5mLF0pDQpgYGANCg0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCg0KZmlsYV9saW5lYWxpZGFkIDwtIGMocm91bmQocmVzZXR0ZXN0KG1vZGVsLjIsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjIsXSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJlc2V0dGVzdChtb2RlbC4yaW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4yaW5mLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICAiUmVzZXR0ZXN0IikNCg0KDQpmaWxhX25vcm1hbGlkYWQgPC0gYyhyb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMikpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMmluZikpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICAiVGVzdCBTaGFwaXJvIFdpbGsiKQ0KZmlsYV9tZWRpYU8gPC0gYyh0LnRlc3QocmVzaWQobW9kZWwuMiksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgdC50ZXN0KHJlc2lkKG1vZGVsLjJpbmYpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgICJ0LXRlc3QiKQ0KZmlsYV92YXJfY3RlIDwtIGMocm91bmQobmN2VGVzdChtb2RlbC4yKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgcm91bmQobmN2VGVzdChtb2RlbC4yaW5mKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgIlRlc3QgbmN2IikNCiAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgDQpmaWxhX2NvcnIgPC0gYyhkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjIpJHAsDQogICAgICAgICAgICAgICBkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjJpbmYpJHAsDQogICAgICAgICAgICAgICAiVGVzdCBkZSBEdXJiaW4tV2F0c29uIikNCiANCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IHJlcCgwLDUpLCIyIiA9IHJlcCgwLDUpLCIzIiA9IHJlcCgwLDUpLHJvdy5uYW1lcyA9YygiTGluZWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vcm1hbGlkYWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNZWRpYSA9IDAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWYXJpYW56YSBjb25zdGFudGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb3JyZWxhY2nDs24iKSkNCg0KDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDEpIDwtICAgIGMoInRyYWluMjogSDJTICsgTCIsInRyYWluMjogSDJTICsgTCwgc2luIGluZmx1eWVudGVzIiwgIlRlc3QgdXRpbGl6YWRvIikNCg0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX2xpbmVhbGlkYWQNCmRmX3B2YWxfZHJvcF9wMVsyLF0gPC0gZmlsYV9ub3JtYWxpZGFkDQpkZl9wdmFsX2Ryb3BfcDFbMyxdIDwtIGZpbGFfbWVkaWFPDQpkZl9wdmFsX2Ryb3BfcDFbNCxdIDwtIGZpbGFfdmFyX2N0ZQ0KZGZfcHZhbF9kcm9wX3AxWzUsXSA8LSBmaWxhX2NvcnINCg0KDQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KRW4gY2llcnRhIG1hbmVyYSBlcyBub3RhYmxlIHF1ZSBhbCBlbGltaW5hciBudWVzdHJhcyBpbmZsdXllbnRlcyB5IGVuIHVuICpkYXRhc2V0KiB0YW4gcGVxdWXDsW8gbm8gZ2VuZXJlIGEgcGVuYXMgZGlmZXJlbmNpYSwgZW4gdG9kbyBjYXNvIG5vcyBtZWpvcmEgdG9kYXMgbGFzIGhpcMOzdGVzaXMgZGVsIG1vZGVsbyBsaW5lYWwsIHNlIHB1ZWRlIGFmaXJtYXIgcXVlIGVzIHVuIG1vZGVsbyBtZWpvciBwYXJhIHRyYWJhamFyIHNvYnJlIGVsIGEgcHJpb3JpLiAgDQoNClRvbWFtb3MgbGEgZGVjaXNpw7NuIGRlIGFjdHVhbGl6YXIgKmNoZWRkYXJbdHJhaW4uMixdKiBjb24gICpjaGVkZGFyW3RyYWluaW5mLjIsXSosIHF1ZSBlcyBsYSB2ZXJzacOzbiBzaW4gb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcy4NCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQp0cmFpbi4yPC10cmFpbi4yaW5mDQptb2RlbC4yPC1tb2RlbC4yaW5mDQpgYGANCiMjIyB0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMyxdICANCkVuIGVzdGUgbW9kZWxvLCBiYWpvIGVsIGNyaXRlcmlvIGRlIGVsZWNjacOzbiBkZSBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIHF1ZSBlbGVnaW1vcyBwYXJhIHRyYXRhciBudWVzdHJvcyBkYXRvcywgZXN0ZSBtb2RlbG8gbm8gcHJlc2VudGFiYSBuaW5ndW5hIG9ic2VydmFjacOzbiBpbmZsdXllbnRlLCBwb3IgbG8gcXVlIHNlIG1hbnRpZW5lIGNvbW8gZXN0w6EuDQoNCg0KIyBFcnJvcmVzIGRlIFRlc3QuIENvbXBhcmFjaW9uIGRlIE1vZGVsb3MNCg0KDQoNCk51ZXN0cm8gcmF6b25hbWllbnRvIHBhcmEgZW5mcmVudGFybm9zIGEgZXN0YSBzZWNjacOzbiBlcyBlbCBzaWd1aWVudGUsIG5vcyBoYW4gc2FsaWRvIGRvcyBtb2RlbG9zIHBvc2libGVzIHkgcGFyYSBjb21wcmVuZGVyIGN1YWwgc2UgYWp1c3RhIG1lam9yIGEgbnVlc3Ryb3MgZGF0b3MgdmFtb3MgYSBlc2NvZ2VyIGNpbmNvIHNlZWRzIHkgZXZhbHVhciBjYWRhIG1vZGVsbyBlbiB0b2RhcyBlbGxhcywgYSBmaW4gZGUgaGFjZXIgdW5hIG1lZGlhIGRlIGxvcyBlcnJvcmVzLg0KDQpQYXJhIGVzdG8gdXNhbW9zIGxhcyB0cmVzIHNlZWRzIHF1ZSBoZW1vcyB1dGlsaXphZG8gYSBsbyBsYXJnbyBkZWwgZG9jdW1lbnRvLCB5IGxlIGHDsWFkaW1vcyBvdHJhcyBkb3MgZWxlZ2lkYXMgYWwgYXphci4gTsOzdGVzZSBxdWUgZXZhbHVhciBlbiBsYSBwcmltZXJhIHNlZWQgeWEgZXN0w6EgaGVjaG8sIHB1ZXMgZW4gZXN0YSBub3Mgc2Fsw61hbiBsb3MgZG9zIG1vZGVsb3MgYSBjb25zaWRlcmFyLiBBZGVtw6FzIGVuIGxhcyBzZWVkcyBkb3MgeSB0cmVzIHlhIGVzdMOhIGhlY2hvIHBhcmEgZWwgbW9kZWxvIGNvbiBIMlMgKyBMYWN0aWMsIHBlcm8gaGF5IHF1ZSByZXBldGlyIGVsIHByb2Nlc28gcGFyYSBlbCBvdHJvIG1vZGVsby4NCkRlIGVzdGEgbWFuZXJhIHJlYWxpemFtb3MgbG9zIG1pc21vcyBjw6FsY3Vsb3MgcXVlIGxvcyByZWFsaXphZG9zIGVuIGxhIHBhcnRlIGRlIGRpYWduw7NzdGljbywgc29icmUgbGFzIGNvbWJpbmFjaW9uZXMuIEVzdG8gZXMsIG5vcyBhc2VndXJhbW9zIHF1ZSBjYWRhIG1vZGVsbyBjb24gdG9kb3MgbG9zIHRyYWluIGN1bXBsYSBsYXMgaGlww7N0ZXNpcyBkZSBub3JtYWxpZGFkLCBtZWRpYSBkZSBlcnJvcmVzIG51bGEsIGhvbW9jZWRhc3RpY2lkYWQsIGxpbmVhbGlkYWQgeSBhdXRvY29ycmVsYWNpw7NuLiBEZXNwdcOpcyBkZSBlc3RvIG5vcyBwbGFudGVhbW9zIHNpIHRpZW5lIGRhdG9zIGluZmx1eWVudGVzIHNlZ8O6biBsYXMgZnVuY2lvbmVzIGFkZWN1YWRhcywgZW4gY2FzbyBkZSB0ZW5lcmxvcyByZWFsaXphbW9zIHVuYSBwcnVlYmEuIGxvcyBxdWl0YW1vcyBkZWwgdHJhaW4geSB2ZW1vcyBzaSBzZSBtZWpvcmEgZWwgcC12YWxvciBkZSBhbGd1bmEgZGUgbGFzIGNhcmFjdGVyw61zdGljYXMgYW50ZXJpb3JlcyB5IGVuIGJhc2UgYSBlc28gZGVjaWRpbW9zIHNpIGVsaW1pbmFtb3MgbGFzIG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMgbyBuby4gDQoNCkNvbiB0b2RvIGVzbyByZWFsaXphZG8gbGxlZ2Ftb3MgYSBsYSBzaWd1aWVudGUgdGFibGEsIHF1ZSBub3MgcGVybWl0ZSBhc3VtaXIgY29tbyB2YWxpZG9zIHRvZG9zIGxvcyBjYXNvcyB5IGNhbGN1bGFyIHN1cyBlcnJvcmVzLg0KDQoNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgSU5UUk9EVUNJUiBTRUNDSU9OIDUNCiMgQ09NUExFVEFSIFRBQkxBIE9VVExJRVJTDQojIENSRU8gUVVFIFRFTklBIFFVRSBQT05FUiBIT01PRVNUIEFSUklCQQ0KIyBKVVNUTyBFTiBFTCBTVU1NQVJZIERFIExBIFNFQ0NJT04gNiBDUkVPIFFVRSBFTCBEQVRBIE5PIERFQkVSSUEgU0VSIENIRUREQVINCg0KIyBWYW1vcyBhIGNvbnNpZGVyYXIgb3RyYXMgZG9zIHNlbWlsbGFzIHBhcmEgZXZhbHVhciBsb3MgbW9kZWxvcyB5IGVsZWdpciBlbCBtZWpvci4NCiMgTGFzIHRvbWFtb3MgZGUgZm9ybWEgcXVlIG5vIGNvaW5jaWRhbiBlbiBsYSBtZWRpZGEgZGUgbG8gcG9zaWJsZSBsb3MgdGVzdHMgZGUgbGFzIGRpc3RpbnRhcyBwYXJ0aWNpb25lcy4NCiMgRGl2aWRpbW9zIGVsIGNvbmp1bnRvIHRvdGFsIHBhcmEgbGFzIGRvcyBzZW1pbGxhcyBudWV2YXMuDQoNCnNldC5zZWVkKCgyMjM0KSkNCnRyYWluLjQgPC0gc2FtcGxlKGMoVFJVRSwgRkFMU0UpLCBzaXplID0gbnJvdyhjaGVkZGFyKSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkNCnRlc3QuNCA8LSAoIXRyYWluLjQpDQpzdW0odGVzdC40KQ0Kc3VtKHRlc3QuMT09VFJVRSAmIHRlc3QuND09VFJVRSkNCnN1bSh0ZXN0LjI9PVRSVUUgJiB0ZXN0LjQ9PVRSVUUpDQpzdW0odGVzdC4zPT1UUlVFICYgdGVzdC40PT1UUlVFKQ0KDQoNCnNldC5zZWVkKCgxMzEpKQ0KdHJhaW4uNSA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC41IDwtICghdHJhaW4uNSkNCnN1bSh0ZXN0LjUpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC41PT1UUlVFKQ0Kc3VtKHRlc3QuMj09VFJVRSAmIHRlc3QuNT09VFJVRSkNCnN1bSh0ZXN0LjM9PVRSVUUgJiB0ZXN0LjU9PVRSVUUpDQpzdW0odGVzdC40PT1UUlVFICYgdGVzdC41PT1UUlVFKQ0KDQp0cmFpbi4xaCA8LSB0cmFpbi4xY3JpdA0KdHJhaW4uMmggPC0gdHJhaW4uMg0KdHJhaW4uM2ggPC0gdHJhaW4uMw0KdHJhaW4uNGggPC0gdHJhaW4uNA0KdHJhaW4uNWggPC0gdHJhaW4uNQ0KDQojIFJlY2FsY3VsYW1vcyB0cmFpbi4yIHBvcnF1ZSBmdWUgbW9kaWZpY2Fkbw0Kc2V0LnNlZWQoMTEwMCkNCnRyYWluLjIgPC0gc2FtcGxlKGMoVFJVRSwgRkFMU0UpLCBzaXplID0gbnJvdyhjaGVkZGFyKSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkNCg0KDQoNCg0KIyBWZWFtc28gc2kgcG9kZW1vcyBlbGltaW5hciBwb3NpYmxlcyBpbmZsdXllbnRlcyBlbiBsb3MgbW9kZWxvcyByZXN0YW50ZXMNCg0KbWgxIDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xaCxdKSAjIGNvbXByb2JhZG9zIHN1cHVlc3Rvcw0KbWgyIDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yaCxdKSAjIGNvbXByb2JhZG9zIHN1cHVlc3Rvcw0KbWgzIDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zaCxdKSAjIGNvbXByb2JhZG9zIHN1cHVlc3Rvcw0KbWg0IDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi40aCxdKQ0KbWg1IDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi41aCxdKQ0KDQptMSA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKSAjIGNvbXByb2JhZG9zIHN1cHVlc3Rvcw0KbTIgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjIsXSkNCm0zIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zLF0pDQptNCA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNCxdKQ0KbTUgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjUsXSkNCg0KDQojIEFsIGlndWFsIHF1ZSBoaWNpbW9zIGVuIDQgY29tcHJvYmFtb3Mgc2kgcmV0aXJhbmRvIG91dGxpZXJzIHkgb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcyBtZWpvcmFuIGxhcyBoaXBvdGVzaXMuDQojICBVbmljYW1lbnRlIGNvbnNpZGVyYXJlbW9zIG9ic2VydmFjaW9uZXMgb2J0ZW5pZGFzIHRhbnRvIHBvciBvdXRsaWVyVGVzdCgpIGNvbW8gcG9yIGluZmx1ZW5jZVBsb3QoKS4NCg0KIyBtaDQNCm91dGxpZXJUZXN0KG1oNCkNCmluZmx1ZW5jZVBsb3QobWg0KSAjIDYsMTIsMTUsMjQNCnBvczRoIDwtIGMocmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDgpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi40aW5mIDwtIHRyYWluLjRoJiFwb3M0aA0KbWg0aW5mIDwtIGxtKHRhc3RlIH4gSDJTK0xhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNGluZixdKQ0KDQpuY3ZUZXN0KG1oNCkNCm5jdlRlc3QobWg0aW5mKSAjIG1lam9yYSBNVUNITw0KDQpzaGFwaXJvLnRlc3QocmVzaWQobWg0KSkNCnNoYXBpcm8udGVzdChyZXNpZChtaDRpbmYpKSAjIG1lam9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG1oNCkNCmR1cmJpbldhdHNvblRlc3QobWg0aW5mKSAjIG1lam9yYQ0KDQpyZXNldHRlc3QobWg0LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi40aW5mLF0pIA0KcmVzZXR0ZXN0KG1oNGluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNGluZixdKSAjIGVtcGVvcmEgcGVybyBlcyBhY2VwdGFibGUNCg0KIyBSZWRlZmluaW1vcyBlbGltaW5hbmRvIHBvczRoIHBvciBzZXIgdGFudGEgbGEgbWVqb3JhIGVuIGhvbW9jZWRhc3RpY2lkYWQgcXVlIGNvbXBlbnNhIGxhIGxpbmVhbGlkYWQNCnRyYWluLjRoIDwtIHRyYWluLjRpbmYNCm1oNCA8LSBtaDRpbmYNCg0KDQojIG1oNQ0Kb3V0bGllclRlc3QobWg1KQ0KaW5mbHVlbmNlUGxvdChtaDUpICMgNiw3LDgsMTIsMTUNCnBvczVoIDwtIGMocmVwKEZBTFNFLDUpLFRSVUUsVFJVRSxUUlVFLHJlcChGQUxTRSwzKSxUUlVFLHJlcChGQUxTRSwyKSxUUlVFLHJlcChGQUxTRSwxNSkpDQoNCnRyYWluLjVpbmYgPC0gdHJhaW4uNWgmIXBvczVoDQptaDVpbmYgPC0gbG0odGFzdGUgfiBIMlMrTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi41aW5mLF0pDQoNCm5jdlRlc3QobWg1KQ0KbmN2VGVzdChtaDVpbmYpICMgbWVqb3JhIA0KDQpzaGFwaXJvLnRlc3QocmVzaWQobWg1KSkNCnNoYXBpcm8udGVzdChyZXNpZChtaDVpbmYpKSAjIGVtcGVvcmENCg0KZHVyYmluV2F0c29uVGVzdChtaDUpDQpkdXJiaW5XYXRzb25UZXN0KG1oNWluZikgIyBhIHZlY2VzIG5vIHNlIGN1bXBsZSBsYSBoaXBvdGVzaXMgbnVsYSBkZSBubyBhdXRvY29ycmVsYWNpb24NCg0KcmVzZXR0ZXN0KG1oNSwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNWluZixdKSANCnJlc2V0dGVzdChtaDVpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjVpbmYsXSkgIyBlbXBlb3JhDQoNCiMgRGVjaWRpbW9zIG5vIGFjdHVhbGl6YXIgZWwgbW9kZWxvIHB1ZXMgbm8gc2llbXByZSBzZSByZWNoYXphIGxhIGNvcnJlbGFjaW9uIHkgZW1wZW9yYW4gb3Ryb3MgcC12YWxvcmVzLg0KDQoNCiMgbTINCm91dGxpZXJUZXN0KG0yKQ0KaW5mbHVlbmNlUGxvdChtMikgIyAxLDEyLDE1LDE4LDI0DQpwb3MyIDwtIGMoVFJVRSxyZXAoRkFMU0UsMTApLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi4yaW5mIDwtIHRyYWluLjImIXBvczINCm0yaW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yaW5mLF0pDQoNCm5jdlRlc3QobTIpDQpuY3ZUZXN0KG0yaW5mKSAjIGVtcGVvcmEgbGlnZXJhbWVudGUNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG0yKSkNCnNoYXBpcm8udGVzdChyZXNpZChtMmluZikpICMgZW1wZW9yYSBsaWdlcmFtZW50ZQ0KDQpkdXJiaW5XYXRzb25UZXN0KG0yKQ0KZHVyYmluV2F0c29uVGVzdChtMmluZikgIyBlbXBlb3JhIGJhc3RhbnRlDQoNCnJlc2V0dGVzdChtMiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMmluZixdKSANCnJlc2V0dGVzdChtMmluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMmluZixdKSAjIG1lam9yYQ0KDQojIERlY2ljaW1vcyBubyByZWRlZmluaXJsbywgeWEgcXVlIGVtcGVvcmEgZW4gbXVjaGFzIHkgbWVqb3JhIGJhc3RhbnRlIGVuIHVuYQ0KDQoNCiMgbTMNCm91dGxpZXJUZXN0KG0zKQ0KaW5mbHVlbmNlUGxvdChtMykgIyAxLDE1LDE5LDI0DQpwb3MzIDwtIGMoVFJVRSxyZXAoRkFMU0UsMTMpLFRSVUUscmVwKEZBTFNFLDMpLFRSVUUscmVwKEZBTFNFLDQpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi4zaW5mIDwtIHRyYWluLjMmIXBvczMNCm0zaW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zaW5mLF0pDQoNCm5jdlRlc3QobTMpDQpuY3ZUZXN0KG0zaW5mKSAjIG1lam9yYSBwb2NvDQoNCnNoYXBpcm8udGVzdChyZXNpZChtMykpDQpzaGFwaXJvLnRlc3QocmVzaWQobTNpbmYpKSAjIG1lam9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG0zKQ0KZHVyYmluV2F0c29uVGVzdChtM2luZikgIyBlbXBlb3JhDQoNCnJlc2V0dGVzdChtMywgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uM2luZixdKSANCnJlc2V0dGVzdChtM2luZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uM2luZixdKSAjIGVtcGVvcmEgY2FzaSBsbyBwaWVyZGUNCg0KIyBEZWNpZGltb3Mgbm8gcmVkZWZpbmlybG8gcG9yIGVzdGFyIGFsIGJvcmRlIGVuIHVuIGNyaXRlcmlvIHkgbm8gbWVqb3JhciBtdWNobyBlbiBvdHJvcw0KDQoNCiMgbTQNCm91dGxpZXJUZXN0KG00KQ0KaW5mbHVlbmNlUGxvdChtNCkgIyA2LDEyLDE1LDIwLDI0DQpwb3M0IDwtIGMocmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDQpLFRSVUUscmVwKEZBTFNFLDMpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi40aW5mIDwtIHRyYWluLjQmIXBvczQNCm00aW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi40aW5mLF0pDQoNCm5jdlRlc3QobTQpDQpuY3ZUZXN0KG00aW5mKSAjIGVtcGVvcmEgYmFzdGFudGUNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG00KSkNCnNoYXBpcm8udGVzdChyZXNpZChtNGluZikpICMgZW1wZW9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG00KQ0KZHVyYmluV2F0c29uVGVzdChtNGluZikjIGVtcGVvcmEgYmFzdGFudGUNCg0KcmVzZXR0ZXN0KG00LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi40aW5mLF0pIA0KcmVzZXR0ZXN0KG00aW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi40aW5mLF0pICMgbWVqb3JhIGFsZ28NCg0KIyBEZWNpZGltb3Mgbm8gY2FtYmlhcmxvIHBvcnF1ZSBlbXBlb3JhIGVuIGNhc2kgdG9kbywgeSBkZSBwb3Igc2kgdGVuaWEgYnVlbm9zIHAtdmFsdWVzDQoNCg0KIyBtNQ0Kb3V0bGllclRlc3QobTUpDQppbmZsdWVuY2VQbG90KG01KSAjIDEsOCwxMiwxNSwxOCwyNA0KcG9zNSA8LSBjKFRSVUUscmVwKEZBTFNFLDYpLFRSVUUscmVwKEZBTFNFLDMpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi41aW5mIDwtIHRyYWluLjUmIXBvczUNCm01aW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi41aW5mLF0pDQoNCm5jdlRlc3QobTUpDQpuY3ZUZXN0KG01aW5mKSAjIGVtcGVvcmEgYmFzdGFudGUNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG01KSkNCnNoYXBpcm8udGVzdChyZXNpZChtNWluZikpICMgbWVqb3JhIA0KDQpkdXJiaW5XYXRzb25UZXN0KG01KQ0KZHVyYmluV2F0c29uVGVzdChtNWluZikgIyBubyBzZSB2ZXJpZmljYSBsYSBoaXBvdGVzaXMgbnVsYSBkZSBubyBhdXRvY29ycmVsYWNpb24NCg0KcmVzZXR0ZXN0KG01LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi41aW5mLF0pIA0KcmVzZXR0ZXN0KG01aW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi41aW5mLF0pICMgZW1wZW9yYQ0KDQojIERlY2lkaW1vcyBubyBjYW1iaWFybG8gcG9yIHBlcmRlcnNlIGxhIGNvcnJlbGFjacOzbg0KDQojIE5vdGVzZSBxdWUgZW4gbG9zIG9yaWdpbmFsZXMgc2llbXByZSBzZSBjdW1wbGlhbiBsYXMgaGlwb3Rlc2lzLCBhdW5xdWUgbm8gZXJhIG5lY2VzYXJpbyBwYXJhIGVsIHByb2Nlc28NCg0KDQoNCg0KbGlzdGFfdGVzdCA8LSBsaXN0KHRlc3QuMSx0ZXN0LjIsdGVzdC4zLHRlc3QuNCx0ZXN0LjUpDQpsaXN0YV90cmFpbmggPC0gbGlzdCh0cmFpbi4xaCx0cmFpbi4yaCx0cmFpbi4zaCx0cmFpbi40aCx0cmFpbi41aCkNCmxpc3RhX3RyYWluIDwtIGxpc3QodHJhaW4uMSx0cmFpbi4yLHRyYWluLjMsdHJhaW4uNCx0cmFpbi41KQ0KDQoNCm1vZGVsb3NfaGlwIDwtIGMoIlMxIHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMxIHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMyIHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMyIHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMzIHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMzIHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM0IHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM0IHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM1IHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM1IHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIk5pdmVsIGRlIHNpZ25pZmljYWNpb24iKQ0KDQpoaXBfUkwgPC0gYygiRGlzdHJpYnVjacOzbl9ub3JtYWwiLA0KICAgICAgICAgICAgIk1lZGlhXzAiLA0KICAgICAgICAgICAgIlZhcmlhbnphX25vX2NvbnN0YW50ZSIsDQogICAgICAgICAgICAiTm9fQXV0b2NvcnJlbGFjacOzbiIpDQpwbGFjZWhvbGRlciA8LSB2ZWN0b3IobW9kZSA9ICJsb2dpY2FsIixsZW5ndGggPSAxMSkNCmRmX2hpcFJMIDwtIGRhdGEuZnJhbWUoIjAiID0gcGxhY2Vob2xkZXIsDQogICAgICAgICAgICAgICAgICAgICAgICIxIiA9IHBsYWNlaG9sZGVyLA0KICAgICAgICAgICAgICAgICAgICAgICAiMiIgPSBwbGFjZWhvbGRlciwNCiAgICAgICAgICAgICAgICAgICAgICAgIjMiID0gcGxhY2Vob2xkZXIsDQogICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9IG1vZGVsb3NfaGlwKQ0KDQpjb2xuYW1lcyhkZl9oaXBSTCkgPC0gaGlwX1JMDQoNCnIgPC0gMQ0KZm9yIChkdHJhaW4gaW4gbGlzdGFfdHJhaW5oKXsNCiAgbW9kZWwuSEwubG0gPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsDQogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjaGVkZGFyW2R0cmFpbixdKQ0KICByZXNpZHVvcyA8LSByZXNpZChtb2RlbC5ITC5sbSkNCiAgbmV3X3JvdyA8LSBjKCkNCiAgDQogIHNoYXAgPC0gcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkdW9zKSRwLnZhbHVlLDQpDQogIHQgPC0gdC50ZXN0KHJlc2lkdW9zLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUNCiAgdiA8LSByb3VuZChuY3ZUZXN0KG1vZGVsLkhMLmxtKSRwLDQpDQogIGR3IDwtIHJvdW5kKGR1cmJpbldhdHNvblRlc3QobW9kZWwuSEwubG0pJHAsNCkNCiAgDQogIG5ld19yb3cgPSBjKHNoYXAsdCx2LGR3KQ0KICBkZl9oaXBSTFtyLF0gPC0gbmV3X3Jvdw0KICByID0gciArIDINCn0NCg0KDQpyIDwtIDINCmZvciAoZHRyYWluIGluIGxpc3RhX3RyYWluKXsNCiAgbW9kZWwuTC5sbSA8LSBsbSh0YXN0ZSB+TGFjdGljLA0KICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjaGVkZGFyW2R0cmFpbixdKQ0KICByZXNpZHVvcyA8LSByZXNpZChtb2RlbC5MLmxtKQ0KICBuZXdfcm93IDwtIGMoKQ0KICANCiAgc2hhcCA8LSByb3VuZChzaGFwaXJvLnRlc3QocmVzaWR1b3MpJHAudmFsdWUsNCkNCiAgdCA8LSB0LnRlc3QocmVzaWR1b3MsIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZQ0KICB2IDwtIHJvdW5kKG5jdlRlc3QobW9kZWwuTC5sbSkkcCw0KQ0KICBkdyA8LSByb3VuZChkdXJiaW5XYXRzb25UZXN0KG1vZGVsLkwubG0pJHAsNCkNCiAgDQogIG5ld19yb3cgPSBjKHNoYXAsdCx2LGR3KQ0KICBkZl9oaXBSTFtyLF0gPC0gbmV3X3Jvdw0KICByID0gciArIDINCn0NCmRmX2hpcFJMWzExLF0gPC0gYyhyZXAoMC4wNSw0KSkNCmRmX2hpcFJMICMgVG9kb3MgbG9zIG1vZGVsb3MgY3VtcGxlbiBsYXMgaGlww7N0ZXNpcw0KDQoNCg0KZXJyMSA8LSAwDQpmb3IgKGkgaW4gNSl7DQogIGR0cmFpbiA8LSBsaXN0YV90cmFpbmhbW2ldXQ0KICBkdGVzdCA8LSBsaXN0YV90ZXN0W1tpXV0NCiAgZG1vZCA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbZHRyYWluLF0pDQogIFkgPC0gY2hlZGRhcltkdGVzdCxdJHRhc3RlDQogIFloYXQgPC0gcHJlZGljdChvYmogPSBkbW9kLCBuZXdkYXRhID0gY2hlZGRhcltkdGVzdCxdKQ0KICBlcnIxIDwtIGVycjEgKyBtZWFuKChZIC0gWWhhdCleMikNCn0NCmVycjEgPC0gZXJyMS81DQplcnIxICMgSDJTICsgTEFDVElDIHRpZW5lIGVycm9yIG1lZGlvIDExLjYzDQoNCg0KZXJyMjwtMA0KZm9yIChpIGluIDUpew0KICBkdHJhaW4gPC0gbGlzdGFfdHJhaW5bW2ldXQ0KICBkdGVzdCA8LSBsaXN0YV90ZXN0W1tpXV0NCiAgZG1vZCA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbZHRyYWluLF0pDQogIFkgPC0gY2hlZGRhcltkdGVzdCxdJHRhc3RlDQogIFloYXQgPC0gcHJlZGljdChvYmogPSBkbW9kLCBuZXdkYXRhID0gY2hlZGRhcltkdGVzdCxdKQ0KICBlcnIyIDwtIGVycjIgKyBtZWFuKChZIC0gWWhhdCleMikNCn0NCg0KDQpgYGANCmBgYHtyIHJlbmRlcj1sZW1vbl9wcmludCwgZWNobz1GQUxTRX0NCmRmX2hpcFJMDQoNCg0KYGBgDQpDYWxjdWxhbW9zIGxvcyBlcnJvcmVzIGRlIGNhZGEgbcOpdG9kbyBjb21vIGxhIG1lZGlhIGRlIGxvcyBlcnJvcmVzIGRlbCBtw6l0b2RvIGFwbGljYWRvIGVuIGNhZGEgc2VlZC4gRGUgZXN0YSBtYW5lcmEsIGVsIGVycm9yIG1lZGlvIG9idGVuaWRvIGVzOg0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludCB9DQpkdDwtZGF0YS5mcmFtZSgiMSI9MCwiMiI9MCxyb3cubmFtZXM9YygiZXJyb3JlcyIpKQ0KY29sbmFtZXMoZHQpPC0gYygiTW9kZWxvIEgyUytMYWN0aWMiLCJMYWN0aWMiKQ0KZHRbMSxdPC1jKGVycjEsZXJyMikNCmR0DQpgYGANCg0KQ29tbyBlbCBlcnJvciBkZWwgbW9kZWxvIEgyUyArIExhY3RpYyBlcyBtZW5vciwgZXNlIGVzIGVsIG1vZGVsbyBxdWUgbGxhbWFyZW1vcyBmaW5hbCB5IHF1ZSBzZSBhanVzdGFyw6EgbG8gbWVqb3IgcG9zaWJsZSBhIGxvcyBkYXRvcyBkZSBudWVzdHJvIGZpY2hlcm8uDQoNCiMgQ29uY2x1c2nDs246IHByZXNlbnRhY2nDs24gZGVsIG1vZGVsbyBmaW5hbA0KDQpGaW5hbG1lbnRlIHBvciBjb21wYXJhY2nDs24gZGUgbG9zIGVycm9yZXMgc2FiZW1vcyBxdWUgZWwgbW9kZWxvIGZpbmFsIHF1ZSBwcmVzZW50YW1vcyBlczogdGFzdGUgfiBIMlMgKyBMYWN0aWMgLCBxdWUgdGllbmUgc2VudGlkbyB5YSBxdWUgQWNldGljIG5vIGVyYSBzaWduaWZpY2F0aXZhLiBvdHJvIGhlY2hvIHF1ZSBsbyByZWFmaXJtYSBlcyBxdWUgZW4gbGEgY29uc3RydWNjacOzbiBkZSBtb2RlbG9zIHNhbGllcm9uIGVuIHRvZG9zIGxvcyBjYXNvcyBlc3RlIG1vZGVsbywgc2Fsdm8gZW4gZWwgbcOpdG9kbyBiYWNrd2FyZCB5IGVuIGVsIG3DqXRvZG8gZm9yd2FyZCBkZSBsYSBwcmltZXJhIHNlbWlsbGEuDQoNCjwhLS0gYXF1aSBoYWNlcmxvIHRhYmxhIGNvbiBsbyBxdWUgbWUgaW50ZXJlc2EgLS0+DQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KbW9kZWwueSA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYyxkYXRhPWNoZWRkYXIpIA0KZGZfcmVzdW1lbiA8LSB0aWR5KG1vZGVsLnkpDQoNCmBgYA0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KZGZfcmVzdW1lbg0KYGBgDQoNClByZXNlbnRhbW9zIGVsIHN1bW1hcnkgZGUgbnVlc3RybyBtb2RlbG8sIGRlbCBxdWUgc2FjYXJlbW9zIG3DoXMgaW5mb3JtY2nDs24gZW4gdW4gZnV0dXJvLg0KDQpBIHN1IHZleiBlbnNlw7FhbW9zIGxvcyBncmFmaWNvcyBkZSBlc3RlIG1vZGVsbzoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTYuNSxmaWcuYWxpZ24gPSAnY2VudGVyJ30NCnBhcihtZnJvdz1jKDIsMikpDQpwbG90KG1vZGVsLnkpDQpgYGANCg0KQWhvcmEgdmFtb3MgYSBhc2VndXJhcm5vcyBxdWUgdmVyaWZpY2EgbGFzIGhpcMOzdGVzaXMgcGFyYSB1bmEgcmVncmVzacOzbiBsaW5lYWwgeSBhZGVtw6FzIGRlIHJldmlzYXIgY29uIG91dGxpZXJUZXN0ICBxdWUgbm8gdGVuZW1vcyBvdXRsaWVycy4NClRhbWJpw6luIHBsYW50ZWFtb3MgdW5hIGhpcMOzdGVzaXMgc29icmUgbGEgbnVsaWRhZCBkZSBsYSBtZWRpYSBkZSBsb3MgZXJyb3JlcyB5IHZlbW9zIHF1ZSBzdSB2YXJpYW56YSBlcyBjb25zdGFudGUgYWRlbcOhcyBkZSBjYWxjdWxhcmxhLg0KPCEtLSBBcXVpIGRlYmVyw61hIGlyIHRhYmxhIGNvbiBwdmFsdWVzIGRlIG5vcm1hbGlkYWQuLi4uIC0tPg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsMSksIjIiID0gcmVwKDAsMSksIjMiID0gcmVwKDAsMSksIjQiID0gcmVwKDAsMSksIjUiID0gcmVwKDAsMSksIjYiID0gcmVwKDAsMSksIjciID0gcmVwKDAsMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9YygibW9kZWwueSIpKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSAgICBjKCJwLU91dGxpZXJzIiwicC1Ob3JtYWxpZGFkIiwicC1NZWRpYSBudWxhIiwicC1Ib21vY2VkYXN0aWNpZGFkIiwiVmFsb3IgZGUgdmFyaWFuemEiLCJwLUF1dG9jb3JyZWxhY2nDs24iLCJwLUxpbmVhbGlkYWQiKQ0KZGZfcHZhbF9kcm9wX3AxWywxXSA8LSBvdXRsaWVyVGVzdChtb2RlbC55KSRwDQpkZl9wdmFsX2Ryb3BfcDFbLDJdIDwtIHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC55KSkkcA0KZGZfcHZhbF9kcm9wX3AxWywzXSA8LSB0LnRlc3QocmVzaWQobW9kZWwueSksbXU9MCxhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlDQpkZl9wdmFsX2Ryb3BfcDFbLDRdIDwtIG5jdlRlc3QobW9kZWwueSkkcA0KZGZfcHZhbF9kcm9wX3AxWyw1XSA8LSBzcXJ0KGRldmlhbmNlKG1vZGVsLnkpL2RmLnJlc2lkdWFsKG1vZGVsLnkpKQ0KZGZfcHZhbF9kcm9wX3AxWyw2XSA8LSBkdXJiaW5XYXRzb25UZXN0KG1vZGVsLnkpJHANCmRmX3B2YWxfZHJvcF9wMVssN10gPC0gcmVzZXR0ZXN0KG1vZGVsLnksIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyKSRwLnZhbHVlDQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQpEaWNobyBlc3RvIHByb2NlZGVtb3MgYSBsYSBwcmVzZW50YWNpw7NuIGRlbCBtb2RlbG8gY29uIHN1cyBiZXRhcyBhc29jaWFkb3MsIHF1ZSBzaSBiaWVuIHNlIHB1ZWRlbiByZWNvZ2VyIGRlbCBzdW1tYXJ5LCB0YW1iacOpbiBsb3MgY2FsY3VsYW1vcyBkZSBmb3JtYSBtYXRyaWNpYWwgaWd1YWwgcXVlIHNlIGhpem8gY29uIGVsIG1vZGVsbyBjb21wbGV0byBlbiBzdSBtb21lbnRvLg0KDQpFbCByZXN1bHRhZG8gc2Vyw61hICoqdGFzdGUgfiAtMjcuNTkxODE1ICszLjk5NDYyNjcgSDJTICsxOS44ODcyMDQgTGFjdGljKioNCk7Ds3Rlc2UgcXVlIHNpZ3VlIHNpZW5kbyBhY29yZGUgYWwgbW9kZWxvIGNvbXBsZXRvIGRvbmRlIGVsICRcYmV0YSQgZGUgTGFjdGljIGVzIG11eSBzdXBlcmlvciBlbiBjb21wYXJhY2nDs24gYWwgZGUgSDJTLg0KDQpQcmVzZW50YW1vcyBhaG9yYSAkUl57Mn0kIHkgJFJeezJ9X3thZGp9JCwgZXN0YXMgY29tbyBhbnRlcyBzZSBwdWVkZW4gcmVjb2dlciBkaXJlY3RhbWVudGUgZGVsIHN1bW1hcnksIHRhbWJpw6luIGxhcyBjYWxjdWxhbW9zIGEgcGFydGlyIGRlIGxvcyBlcnJvcmVzIHkgbGEgdGFibGEgYW5vdmEsIGRhbmRvIGVsIHJlc3VsdGFkbyBkZSAwLjY1MTcwMjQgeSAwLjYyNTkwMjUgcmVzcGVjdGl2YW1lbnRlLiBBZGVtw6FzIHByZXNlbnRhbW9zIGVsIHZlY3RvciBkZSBwLXZhbG9yZXMuDQoNCjwhLS0gQXF1aSBpcmlhIHVuIHRhYmxhIHF1ZSBwcmVzZW50ZSB0b2RvIGVsbG8gLS0+DQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQojc3VtbWFyeShtb2RlbC55KSRjb2VmZlssNF0NCg0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsMSksIjIiID0gcmVwKDAsMSksIjMiID0gcmVwKDAsMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9YygiUC12YWxvcmVzIikpDQoNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gICAgYygiSW50ZXJjZXB0IiwiSDJTIiwiTGFjdGljIikNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gYyhzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmW1sxLDRdXSxzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmW1syLDRdXSxzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmW1szLDRdXSkNCg0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCk9ic2VydmFtb3MgcXVlIHRvZG9zIGxvcyBwLXZhbG9yZXMgZXN0w6FuIHBvciBkZWJham8gZGUgbnVlc3RyYSBhbHBoYSBkZSByZWZlcmVuY2lhLg0KDQpUYW1iacOpbiBwcmVzZW50YW1vcyBpbnRlcnZhbG9zIHBhcmEgbGFzIGJldGFzIGRlIEJvbmZlcnJvbmkgeSBTY2hlZmbDqToNCjwhLS0gQXF1aSB2YSBlc28gLS0+DQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQphbHBoYSA8LSAwLjEwDQpiIDwtIHN1bW1hcnkobW9kZWwueSkkY29lZlsyOjMsIDFdDQpzLmIgPC0gc3VtbWFyeShtb2RlbC55KSRjb2VmWzI6MywgMl0NCmcgPC0gMw0KbiA8LSBucm93KGNoZWRkYXIpDQpwIDwtIG5jb2woc3VtbWFyeShtb2RlbC55KSRjb2VmKQ0KdF90ZW8gPC0gcXQoMSAtIGFscGhhIC8gKDIgKiBnKSwgbiAtIHApDQpCb21TaW1DSSA8LSBtYXRyaXgoYyhiIC0gdF90ZW8gKiBzLmIsIGIgKyB0X3RlbyAqIHMuYiksIG5jb2wgPSAyKQ0KY29uZiA8LSBjKCI1JSIsICI5NSUiKQ0KYm5hbSA8LSBjKCJIMlMiLCAiTGFjdGljIikNCmRpbW5hbWVzKEJvbVNpbUNJKSA8LSBsaXN0KGJuYW0sIGNvbmYpDQojIEJvbVNpbUNJDQpjMTwtQm9tU2ltQ0lbMSxdDQpjMjwtQm9tU2ltQ0lbMixdDQpRIDwtIHAgLSAxDQpmX3RlbyA8LSBxZigwLjksIFEsIG4gLSBwKSMwLjkgbm8gc2VyaWEgMC45NT8NClNjaFNpbUNJIDwtIG1hdHJpeChjKGIgLSBzcXJ0KFEgKiBmX3RlbykgKiBzLmIsIGIgKyBzcXJ0KFEgKiBmX3RlbykgKiBzLmIpLCBuY29sID0gMikNCmNvbmYgPC0gYygiNSUiLCAiOTUlIikNCmJuYW0gPC0gYygiSDJTIiwgIkxhY3RpYyIpDQpkaW1uYW1lcyhTY2hTaW1DSSkgPC0gbGlzdChibmFtLCBjb25mKQ0KIyBTY2hTaW1DSQ0KZDE8LVNjaFNpbUNJWzEsXQ0KZDI8LVNjaFNpbUNJWzIsXQ0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsMyksIjIiID0gcmVwKDAsMyksIjMiID0gcmVwKDAsMyksIjQiID0gcmVwKDAsMyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9YygiSDJTIiwiTGFjdGljIiwiUG9yY2VudGFqZSIpKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSAgICBjKCJCb25mZXJyb25pIiwiQm9uZmVycm9uaSIsIlNjaGVmZsOpIiwiU2NoZWZmw6kiKQ0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBjKGMxLGQxKQ0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBjKGMyLGQyKQ0KZGZfcHZhbF9kcm9wX3AxWzMsXSA8LSBjKCI1JSIsIjk1JSIsIjUlIiwiOTUlIikNCmRmX3B2YWxfZHJvcF9wMQ0KYGBgDQpGaW5hbG1lbnRlIGJ1c2NhbW9zIHVuYSByZXByZXNlbnRhY2nDs24gZGUgbGEgcmVncmVzacOzbiBxdWUgdGVuZW1vcyBlbiAzIGRpbWVuc2lvbmVzIHlhIHF1ZSBlbCBtb2RlbG8gZmluYWwgY29uc3RhIGRlIHVuYSB2YXJpYWJsZSByZXNwdWVzdGEgeSBkb3MgcHJlZGljdG9yYXMgeSB2ZW1vcyBlbCBwbGFubyBkZSByZWdyZXNpw7NuLCBtYXJjYW5kbyBlbiByb2pvIGxhcyBvYnNlcnZhY2lvbmVzIHF1ZSBwZW9yIHNlIGFqdXN0YW4uDQo8IS0tIEFxdWkgdmEgZXNvLCBzaSBsbyBwdWVkZSBvbmVyIG90cm8gbWVqb3IsIHBxIGEgbWkgaGF5IHVuYSBncmFmaWNhIHF1ZSBubyBzZSBtZSBlamVjdXRhIC0tPg0KDQpgYGB7ciBlY2hvID1GQUxTRX0NCnBhcihtZnJvdz1jKDEsMikpDQpwbG90X2x5KHg9SDJTLCB5PUxhY3RpYywgej10YXN0ZSwgdHlwZT0ic2NhdHRlcjNkIiwgbW9kZT0ibWFya2VycyIsIGNvbG9yPXRhc3RlKSAlPiUgDQogIGxheW91dChzY2VuZSA9IGxpc3QoeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0gyUyAoJSknKSwNCiAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnTGFjdGljICglKScpLA0KICAgICAgICAgICAgICAgICAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICdUYXN0ZSAoMC0xMDApJykpKQ0KcGxhbmVyZWcgPC0gc2NhdHRlcnBsb3QzZCh4PUgyUywgeT1MYWN0aWMsIHo9dGFzdGUsIHBjaD0xNiwgY2V4LmxhYj0xLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdobGlnaHQuM2Q9VFJVRSwgdHlwZT0iaCIsIHhsYWI9J0gyUyAoJSknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB5bGFiPSdMYWN0aWMgKCUpJywgemxhYj0nVGFzdGUgKDAtMTAwKScpDQpwbGFuZXJlZyRwbGFuZTNkKG1vZGVsLnksIGx0eS5ib3g9InNvbGlkIiwgY29sPSdtZWRpdW1ibHVlJykNCmBgYA0K